2 * Routines for ICMP - Internet Control Message Protocol
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
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>
15 * SPDX-License-Identifier: GPL-2.0-or-later
17 * Added support for ICMP extensions RFC 4884 and RFC 5837
18 * (c) 2011 Gaurav Tungatkar <gstungat@ncsu.edu>
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>
33 #include <epan/ipproto.h>
34 #include <epan/capture_dissectors.h>
35 #include <epan/proto_data.h>
38 #include <wsutil/array.h>
39 #include <wsutil/pint.h>
41 #include "packet-ip.h"
42 #include "packet-icmp.h"
44 void proto_register_icmp(void);
45 void proto_reg_handoff_icmp(void);
47 static heur_dissector_list_t icmp_heur_subdissector_list
;
50 /* Conversation related data */
51 static int hf_icmp_resp_in
;
52 static int hf_icmp_resp_to
;
53 static int hf_icmp_no_resp
;
54 static int hf_icmp_resptime
;
55 static int hf_icmp_data_time
;
56 static int hf_icmp_data_time_relative
;
58 typedef struct _icmp_conv_info_t
{
59 wmem_tree_t
*unmatched_pdus
;
60 wmem_tree_t
*matched_pdus
;
63 static icmp_transaction_t
*transaction_start(packet_info
* pinfo
,
66 static icmp_transaction_t
*transaction_end(packet_info
* pinfo
,
70 /* Decode the end of the ICMP payload as ICMP MPLS extensions
71 if the packet in the payload has more than 128 bytes */
72 static bool favor_icmp_mpls_ext
;
74 static int proto_icmp
;
76 static int hf_icmp_type
;
77 static int hf_icmp_code
;
78 static int hf_icmp_checksum
;
79 static int hf_icmp_checksum_status
;
80 static int hf_icmp_unused
;
81 static int hf_icmp_reserved
;
82 static int hf_icmp_ident
;
83 static int hf_icmp_ident_le
;
84 static int hf_icmp_seq_num
;
85 static int hf_icmp_seq_num_le
;
86 static int hf_icmp_mtu
;
87 static int hf_icmp_num_addrs
;
88 static int hf_icmp_addr_entry_size
;
89 static int hf_icmp_lifetime
;
90 static int hf_icmp_pointer
;
91 static int hf_icmp_router_address
;
92 static int hf_icmp_pref_level
;
93 static int hf_icmp_redir_gw
;
94 static int hf_icmp_originate_timestamp
;
95 static int hf_icmp_receive_timestamp
;
96 static int hf_icmp_transmit_timestamp
;
97 static int hf_icmp_address_mask
;
98 static int hf_icmp_length
;
99 static int hf_icmp_length_original_datagram
;
102 static int hf_icmp_mip_type
;
103 static int hf_icmp_mip_length
;
104 static int hf_icmp_mip_prefix_length
;
105 static int hf_icmp_mip_seq
;
106 static int hf_icmp_mip_life
;
107 static int hf_icmp_mip_flags
;
108 static int hf_icmp_mip_r
;
109 static int hf_icmp_mip_b
;
110 static int hf_icmp_mip_h
;
111 static int hf_icmp_mip_f
;
112 static int hf_icmp_mip_m
;
113 static int hf_icmp_mip_g
;
114 static int hf_icmp_mip_v
;
115 static int hf_icmp_mip_rt
;
116 static int hf_icmp_mip_u
;
117 static int hf_icmp_mip_x
;
118 static int hf_icmp_mip_reserved
;
119 static int hf_icmp_mip_coa
;
120 static int hf_icmp_mip_challenge
;
121 static int hf_icmp_mip_content
;
123 /* extensions RFC 4884*/
124 static int hf_icmp_ext
;
125 static int hf_icmp_ext_version
;
126 static int hf_icmp_ext_reserved
;
127 static int hf_icmp_ext_checksum
;
128 static int hf_icmp_ext_checksum_status
;
129 static int hf_icmp_ext_length
;
130 static int hf_icmp_ext_class
;
131 static int hf_icmp_ext_c_type
;
132 static int hf_icmp_ext_data
;
134 /* Interface information extension RFC 5837 */
135 static int hf_icmp_int_info_ifindex
;
136 static int hf_icmp_int_info_ipaddr
;
137 static int hf_icmp_int_info_name
;
138 static int hf_icmp_int_info_mtu_present
;
139 static int hf_icmp_int_info_mtu
;
140 static int hf_icmp_int_info_index
;
141 static int hf_icmp_int_info_afi
;
142 static int hf_icmp_int_info_ipv4
;
143 static int hf_icmp_int_info_ipv6
;
144 static int hf_icmp_int_info_ipunknown
;
145 static int hf_icmp_int_info_name_length
;
146 static int hf_icmp_int_info_name_string
;
147 static int hf_icmp_int_info_role
;
148 static int hf_icmp_int_info_reserved
;
149 static int ett_icmp_interface_info_object
;
150 static int ett_icmp_interface_ipaddr
;
151 static int ett_icmp_interface_name
;
152 /* MPLS extension object*/
153 static int hf_icmp_mpls_label
;
154 static int hf_icmp_mpls_exp
;
155 static int hf_icmp_mpls_s
;
156 static int hf_icmp_mpls_ttl
;
157 static int hf_icmp_mpls_data
;
160 static int ett_icmp_mip
;
161 static int ett_icmp_mip_flags
;
164 static int ett_icmp_ext
;
165 static int ett_icmp_ext_object
;
167 /* MPLS extensions */
168 static int ett_icmp_mpls_stack_object
;
170 static expert_field ei_icmp_type_deprecated
;
171 static expert_field ei_icmp_resp_not_found
;
172 static expert_field ei_icmp_checksum
;
173 static expert_field ei_icmp_ext_checksum
;
175 /* Extended Echo - Probe */
176 static int hf_icmp_ext_echo_seq_num
;
177 static int hf_icmp_ext_echo_req_reserved
;
178 static int hf_icmp_ext_echo_req_local
;
179 static int hf_icmp_ext_echo_rsp_state
;
180 static int hf_icmp_ext_echo_rsp_reserved
;
181 static int hf_icmp_ext_echo_rsp_active
;
182 static int hf_icmp_ext_echo_rsp_ipv4
;
183 static int hf_icmp_ext_echo_rsp_ipv6
;
184 static int hf_icmp_int_ident_name_string
;
185 static int hf_icmp_int_ident_index
;
186 static int hf_icmp_int_ident_afi
;
187 static int hf_icmp_int_ident_addr_length
;
188 static int hf_icmp_int_ident_reserved
;
189 static int hf_icmp_int_ident_ipv4
;
190 static int hf_icmp_int_ident_ipv6
;
191 static int hf_icmp_int_ident_address
;
193 static dissector_handle_t icmp_handle
;
196 /* ICMP definitions */
197 #define ICMP_ECHOREPLY 0
198 #define ICMP_UNREACH 3
199 #define ICMP_SOURCEQUENCH 4
200 #define ICMP_REDIRECT 5
201 #define ICMP_ALTHOST 6
203 #define ICMP_RTRADVERT 9
204 #define ICMP_RTRSOLICIT 10
205 #define ICMP_TIMXCEED 11
206 #define ICMP_PARAMPROB 12
207 #define ICMP_TSTAMP 13
208 #define ICMP_TSTAMPREPLY 14
210 #define ICMP_IREQREPLY 16
211 #define ICMP_MASKREQ 17
212 #define ICMP_MASKREPLY 18
213 #define ICMP_PHOTURIS 40
214 #define ICMP_EXTECHO 42
215 #define ICMP_EXTECHOREPLY 43
217 /* ICMP UNREACHABLE */
218 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
219 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
220 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
221 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
222 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
223 #define ICMP_SR_FAILED 5 /* Source Route failed */
224 #define ICMP_NET_UNKNOWN 6
225 #define ICMP_HOST_UNKNOWN 7
226 #define ICMP_HOST_ISOLATED 8
227 #define ICMP_NET_ANO 9
228 #define ICMP_HOST_ANO 10
229 #define ICMP_NET_UNR_TOS 11
230 #define ICMP_HOST_UNR_TOS 12
231 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
232 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
233 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
235 #define ICMP_MIP_EXTENSION_PAD 0
236 #define ICMP_MIP_MOB_AGENT_ADV 16
237 #define ICMP_MIP_PREFIX_LENGTHS 19
238 #define ICMP_MIP_CHALLENGE 24
240 static dissector_handle_t ip_handle
;
242 /* RFC 6633 and 6918 formally deprecated a number of types, including
243 * those never widely implemented nor deployed (in Wireshark or elsewhere.)
245 static const value_string icmp_type_str
[] = {
246 {ICMP_ECHOREPLY
, "Echo (ping) reply"},
249 {ICMP_UNREACH
, "Destination unreachable"},
250 {ICMP_SOURCEQUENCH
, "Source quench (flow control)"}, /* Deprecated */
251 {ICMP_REDIRECT
, "Redirect"},
252 {ICMP_ALTHOST
, "Alternate host address"}, /* Deprecated */
253 {ICMP_ECHO
, "Echo (ping) request"},
254 {ICMP_RTRADVERT
, "Router advertisement"},
255 {ICMP_RTRSOLICIT
, "Router solicitation"},
256 {ICMP_TIMXCEED
, "Time-to-live exceeded"},
257 {ICMP_PARAMPROB
, "Parameter problem"},
258 {ICMP_TSTAMP
, "Timestamp request"},
259 {ICMP_TSTAMPREPLY
, "Timestamp reply"},
260 {ICMP_IREQ
, "Information request"}, /* Deprecated */
261 {ICMP_IREQREPLY
, "Information reply"}, /* Deprecated */
262 {ICMP_MASKREQ
, "Address mask request"}, /* Deprecated */
263 {ICMP_MASKREPLY
, "Address mask reply"}, /* Deprecated */
264 {19, "Reserved (for security)"},
265 {30, "Traceroute"}, /* Deprecated */
266 {31, "Datagram Conversion Error"}, /* Deprecated */
267 {32, "Mobile Host Redirect"}, /* Deprecated */
268 {33, "IPv6 Where-Are-You"}, /* Deprecated */
269 {34, "IPv6 I-Am-Here"}, /* Deprecated */
270 {35, "Mobile Registration Request"}, /* Deprecated */
271 {36, "Mobile Registration Reply"}, /* Deprecated */
272 {37, "Domain Name Request"}, /* Deprecated */
273 {38, "Domain Name Reply"}, /* Deprecated */
274 {39, "SKIP"}, /* Deprecated */
275 {ICMP_PHOTURIS
, "Photuris"},
276 {41, "Experimental mobility protocols"},
277 {ICMP_EXTECHO
, "Extended Echo request"},
278 {ICMP_EXTECHOREPLY
, "Extended Echo reply"},
282 static const value_string unreach_code_str
[] = {
283 {ICMP_NET_UNREACH
, "Network unreachable"},
284 {ICMP_HOST_UNREACH
, "Host unreachable"},
285 {ICMP_PROT_UNREACH
, "Protocol unreachable"},
286 {ICMP_PORT_UNREACH
, "Port unreachable"},
287 {ICMP_FRAG_NEEDED
, "Fragmentation needed"},
288 {ICMP_SR_FAILED
, "Source route failed"},
289 {ICMP_NET_UNKNOWN
, "Destination network unknown"},
290 {ICMP_HOST_UNKNOWN
, "Destination host unknown"},
291 {ICMP_HOST_ISOLATED
, "Source host isolated"},
292 {ICMP_NET_ANO
, "Network administratively prohibited"},
293 {ICMP_HOST_ANO
, "Host administratively prohibited"},
294 {ICMP_NET_UNR_TOS
, "Network unreachable for TOS"},
295 {ICMP_HOST_UNR_TOS
, "Host unreachable for TOS"},
296 {ICMP_PKT_FILTERED
, "Communication administratively filtered"},
297 {ICMP_PREC_VIOLATION
, "Host precedence violation"},
298 {ICMP_PREC_CUTOFF
, "Precedence cutoff in effect"},
302 static const value_string redir_code_str
[] = {
303 {0, "Redirect for network"},
304 {1, "Redirect for host"},
305 {2, "Redirect for TOS and network"},
306 {3, "Redirect for TOS and host"},
310 static const value_string alt_host_code_str
[] = {
311 {0, "Alternate address for host"},
315 static const value_string rtradvert_code_str
[] = {
316 { 0, "Normal router advertisement"},
317 {16, "Does not route common traffic"},
321 static const value_string ttl_code_str
[] = {
322 {0, "Time to live exceeded in transit"},
323 {1, "Fragment reassembly time exceeded"},
327 static const value_string par_code_str
[] = {
328 {0, "Pointer indicates the error"},
329 {1, "Required option missing"},
334 static const value_string photuris_code_str
[] = {
336 {1, "Authentication Failed"},
337 {2, "Decompression Failed"},
338 {3, "Decryption Failed"},
339 {4, "Need Authentication"},
340 {5, "Need Authorization"},
344 static const value_string ext_echo_req_code_str
[] = {
349 static const value_string ext_echo_reply_code_str
[] = {
351 {1, "Malformed Query"},
352 {2, "No Such Interface"},
353 {3, "No Such Table Entry"},
354 {4, "Multiple Interfaces Satisfy Query"},
358 static const value_string ext_echo_reply_state_str
[] = {
369 #define ICMP_EXT_ECHO_IDENT_NAME 1
370 #define ICMP_EXT_ECHO_IDENT_INDEX 2
371 #define ICMP_EXT_ECHO_IDENT_ADDRESS 3
373 static const value_string ext_echo_ident_str
[] = {
374 {ICMP_EXT_ECHO_IDENT_NAME
, "Identifies Interface By Name"},
375 {ICMP_EXT_ECHO_IDENT_INDEX
, "Identifies Interface By Index"},
376 {ICMP_EXT_ECHO_IDENT_ADDRESS
, "Identifies Interface By Address"},
380 static const value_string mip_extensions
[] = {
381 {ICMP_MIP_EXTENSION_PAD
, "One byte padding extension"}, /* RFC 2002 */
382 {ICMP_MIP_MOB_AGENT_ADV
, "Mobility Agent Advertisement Extension"},
384 {ICMP_MIP_PREFIX_LENGTHS
, "Prefix Lengths Extension"}, /* RFC 2002 */
385 {ICMP_MIP_CHALLENGE
, "Challenge Extension"}, /* RFC 3012 */
389 static const value_string icmp_ext_class_str
[] = {
390 {1, "MPLS Label Stack Class"},
391 {2, "Interface Information Object"},
392 {3, "Interface Identification Object"},
396 /* RFC 5837 ICMP extension - Interface Information Object
399 static const value_string interface_role_str
[] = {
400 {0, "IP interface upon which datagram arrived"},
401 {1, "Sub-IP component of an IP interface upon which datagram arrived"},
402 {2, "IP interface through which datagram would be forwarded"},
403 {3, "IP next-hop to which datagram would be forwarded"},
407 #define INT_INFO_INTERFACE_ROLE 0xc0
408 #define INT_INFO_RESERVED 0x30
409 #define INT_INFO_IFINDEX 0x08
410 #define INT_INFO_IPADDR 0x04
411 #define INT_INFO_NAME 0x02
412 #define INT_INFO_MTU 0x01
414 #define INTERFACE_INFORMATION_OBJECT_CLASS 2
416 #define INTERFACE_IDENTIFICATION_OBJECT_CLASS 3
418 #define MPLS_STACK_ENTRY_OBJECT_CLASS 1
419 #define MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS 0
421 #define MPLS_STACK_ENTRY_C_TYPE 1
422 #define MPLS_EXTENDED_PAYLOAD_C_TYPE 1
424 /* Return true if the address is in the 224.0.0.0/4 network block */
425 #define is_a_multicast_addr(a) in4_addr_is_multicast(a)
427 /* Return true if the address is the 255.255.255.255 broadcast address */
428 #define is_a_broadcast_addr(a) ((a) == 0xffffffffU)
431 * We check the address type in case some bogus IPv6 packet specifies ICMP
432 * rather than ICMP6 in the next header field.
434 #define ADDR_IS_MULTICAST(addr) \
435 (((addr)->type == AT_IPv4) && is_a_multicast_addr(pntoh32((addr)->data)))
437 #define ADDR_IS_BROADCAST(addr) \
438 (((addr)->type == AT_IPv4) && is_a_broadcast_addr(pntoh32((addr)->data)))
440 #define ADDR_IS_NOT_UNICAST(addr) \
441 (ADDR_IS_MULTICAST(addr) || ADDR_IS_BROADCAST(addr))
444 /* whenever a ICMP packet is seen by the tap listener */
445 /* Add a new frame into the graph */
446 static tap_packet_status
447 icmp_seq_analysis_packet( void *ptr
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *dummy _U_
, tap_flags_t flags _U_
)
449 seq_analysis_info_t
*sainfo
= (seq_analysis_info_t
*) ptr
;
450 seq_analysis_item_t
*sai
= sequence_analysis_create_sai_with_addresses(pinfo
, sainfo
);
453 return TAP_PACKET_DONT_REDRAW
;
455 sai
->frame_number
= pinfo
->num
;
457 sequence_analysis_use_color_filter(pinfo
, sai
);
459 sai
->port_src
=pinfo
->srcport
;
460 sai
->port_dst
=pinfo
->destport
;
462 sequence_analysis_use_col_info_as_label_comment(pinfo
, sai
);
464 if (pinfo
->ptype
== PT_NONE
) {
465 icmp_info_t
*p_icmp_info
= (icmp_info_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_icmp
, 0);
467 if (p_icmp_info
!= NULL
) {
469 sai
->port_dst
= p_icmp_info
->type
* 256 + p_icmp_info
->code
;
477 g_queue_push_tail(sainfo
->items
, sai
);
479 return TAP_PACKET_REDRAW
;
482 static conversation_t
*_find_or_create_conversation(packet_info
* pinfo
)
484 conversation_t
*conv
= NULL
;
486 /* Have we seen this conversation before? */
488 find_conversation(pinfo
->num
, &pinfo
->src
, &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
),
491 /* No, this is a new conversation. */
493 conversation_new(pinfo
->num
, &pinfo
->src
,
494 &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
), 0, 0, 0);
500 * Dissect the mobile ip advertisement extensions.
503 dissect_mip_extensions(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
)
508 proto_tree
*mip_tree
= NULL
;
511 static int * const flags
[] = {
522 &hf_icmp_mip_reserved
,
526 /* Not much to do if we're not parsing everything */
530 while (tvb_reported_length_remaining(tvb
, offset
) > 0) {
531 type
= tvb_get_uint8(tvb
, offset
+ 0);
533 length
= tvb_get_uint8(tvb
, offset
+ 1);
538 mip_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
,
539 1, ett_icmp_mip
, &ti
,
540 "Ext: %s", val_to_str(type
,
543 proto_tree_add_item(mip_tree
, hf_icmp_mip_type
,
547 if (type
!= ICMP_MIP_EXTENSION_PAD
)
549 proto_item_set_len(ti
, length
+ 2);
552 proto_tree_add_item(mip_tree
, hf_icmp_mip_length
,
559 case ICMP_MIP_EXTENSION_PAD
:
560 /* One byte padding extension */
562 case ICMP_MIP_MOB_AGENT_ADV
:
563 /* Mobility Agent Advertisement Extension (RFC 2002) */
565 /* sequence number */
566 proto_tree_add_item(mip_tree
, hf_icmp_mip_seq
, tvb
,
567 offset
, 2, ENC_BIG_ENDIAN
);
569 /* Registration Lifetime */
570 proto_tree_add_item(mip_tree
, hf_icmp_mip_life
,
575 proto_tree_add_bitmask(mip_tree
, tvb
, offset
, hf_icmp_mip_flags
, ett_icmp_mip_flags
, flags
, ENC_BIG_ENDIAN
);
579 numCOAs
= (length
- 6) / 4;
580 for (i
= 0; i
< numCOAs
; i
++) {
581 proto_tree_add_item(mip_tree
,
582 hf_icmp_mip_coa
, tvb
,
588 case ICMP_MIP_PREFIX_LENGTHS
:
589 /* Prefix-Lengths Extension (RFC 2002) */
593 for (i
= 0; i
< length
; i
++) {
594 proto_tree_add_item(mip_tree
,
595 hf_icmp_mip_prefix_length
,
601 case ICMP_MIP_CHALLENGE
:
602 /* Challenge Extension (RFC 3012) */
604 proto_tree_add_item(mip_tree
,
605 hf_icmp_mip_challenge
, tvb
,
606 offset
, length
, ENC_NA
);
613 proto_tree_add_item(mip_tree
, hf_icmp_mip_content
, tvb
, offset
, length
- 4, ENC_NA
);
621 } /* dissect_mip_extensions */
624 dissect_mpls_extended_payload_object(tvbuff_t
* tvb
, int offset
,
625 proto_tree
* ext_object_tree
,
626 proto_item
* tf_object
)
629 uint16_t obj_length
, obj_trunc_length
;
632 unknown_object
= false;
634 obj_length
= tvb_get_ntohs(tvb
, offset
);
637 MIN(obj_length
, tvb_reported_length_remaining(tvb
, offset
));
640 c_type
= tvb_get_uint8(tvb
, offset
+ 3);
641 proto_tree_add_uint(ext_object_tree
, hf_icmp_ext_c_type
, tvb
,
642 offset
+ 3, 1, c_type
);
644 /* skip the object header */
648 case MPLS_EXTENDED_PAYLOAD_C_TYPE
:
649 proto_item_set_text(tf_object
, "Extended Payload");
651 /* This object contains some portion of the original packet
652 that could not fit in the 128 bytes of the ICMP payload */
653 if (obj_trunc_length
> 4) {
654 proto_tree_add_item(ext_object_tree
, hf_icmp_ext_data
, tvb
, offset
, obj_trunc_length
- 4, ENC_NA
);
658 unknown_object
= true;
659 } /* end switch c_type */
660 return unknown_object
;
664 dissect_mpls_stack_entry_object(tvbuff_t
* tvb
, int offset
,
665 proto_tree
* ext_object_tree
,
666 proto_item
* tf_object
)
669 proto_item
*tf_entry
;
670 proto_tree
*mpls_stack_object_tree
;
671 uint16_t obj_length
, obj_trunc_length
;
678 unknown_object
= false;
680 obj_length
= tvb_get_ntohs(tvb
, offset
);
683 MIN(obj_length
, tvb_reported_length_remaining(tvb
, offset
));
684 obj_end_offset
= offset
+ obj_trunc_length
;
686 c_type
= tvb_get_uint8(tvb
, offset
+ 3);
687 proto_tree_add_uint(ext_object_tree
, hf_icmp_ext_c_type
, tvb
,
688 offset
+ 3, 1, c_type
);
690 /* skip the object header */
694 case MPLS_STACK_ENTRY_C_TYPE
:
695 proto_item_set_text(tf_object
, "MPLS Stack Entry");
697 while (offset
+ 4 <= obj_end_offset
) {
698 if (tvb_reported_length_remaining(tvb
, offset
) < 4) {
699 /* Not enough room in the packet ! */
702 /* Create a subtree for each entry (the text will be set later) */
703 mpls_stack_object_tree
= proto_tree_add_subtree(ext_object_tree
,
705 ett_icmp_mpls_stack_object
, &tf_entry
, " ");
708 label
= (unsigned) tvb_get_ntohs(tvb
, offset
);
709 tmp
= tvb_get_uint8(tvb
, offset
+ 2);
710 label
= (label
<< 4) + (tmp
>> 4);
712 proto_tree_add_uint(mpls_stack_object_tree
,
713 hf_icmp_mpls_label
, tvb
,
714 offset
, 3, label
<< 4);
716 proto_item_set_text(tf_entry
, "Label: %u", label
);
718 /* Experimental field (also called "CoS") */
719 proto_tree_add_uint(mpls_stack_object_tree
,
720 hf_icmp_mpls_exp
, tvb
,
723 proto_item_append_text(tf_entry
, ", Exp: %u",
727 proto_tree_add_boolean(mpls_stack_object_tree
,
731 proto_item_append_text(tf_entry
, ", S: %u",
735 ttl
= tvb_get_uint8(tvb
, offset
+ 3);
737 proto_tree_add_item(mpls_stack_object_tree
,
738 hf_icmp_mpls_ttl
, tvb
,
739 offset
+ 3, 1, ENC_BIG_ENDIAN
);
741 proto_item_append_text(tf_entry
, ", TTL: %u", ttl
);
747 if (offset
< obj_end_offset
) {
748 proto_tree_add_item(ext_object_tree
, hf_icmp_mpls_data
, tvb
, offset
, obj_end_offset
- offset
, ENC_NA
);
754 unknown_object
= true;
757 } /* end switch c_type */
758 return unknown_object
;
760 } /* end dissect_mpls_stack_entry_object */
762 /* Dissect Interface Information Object RFC 5837*/
764 dissect_interface_information_object(tvbuff_t
* tvb
, int offset
,
765 proto_tree
* ext_object_tree
,
766 proto_item
* tf_object
)
768 proto_tree
*int_name_object_tree
= NULL
;
769 proto_tree
*int_ipaddr_object_tree
;
770 uint16_t obj_length
, obj_trunc_length
;
774 uint8_t if_index_flag
;
779 uint8_t int_name_length
= 0;
781 unknown_object
= false;
783 obj_length
= tvb_get_ntohs(tvb
, offset
);
786 MIN(obj_length
, tvb_reported_length_remaining(tvb
, offset
));
787 obj_end_offset
= offset
+ obj_trunc_length
;
790 c_type
= tvb_get_uint8(tvb
, offset
+ 3);
792 proto_item_set_text(tf_object
, "Interface Information Object");
793 if (tvb_reported_length_remaining(tvb
, offset
) < 4) {
794 /* Not enough room in the packet ! return unknown_object = true */
798 if_index_flag
= (c_type
& INT_INFO_IFINDEX
) >> 3;
799 ipaddr_flag
= (c_type
& INT_INFO_IPADDR
) >> 2;
800 name_flag
= (c_type
& INT_INFO_NAME
) >> 1;
801 mtu_flag
= (c_type
& INT_INFO_MTU
) >> 0;
804 static int * const c_type_fields
[] = {
805 &hf_icmp_int_info_role
,
806 &hf_icmp_int_info_reserved
,
807 &hf_icmp_int_info_ifindex
,
808 &hf_icmp_int_info_ipaddr
,
809 &hf_icmp_int_info_name
,
810 &hf_icmp_int_info_mtu_present
,
813 proto_tree_add_bitmask(ext_object_tree
, tvb
, offset
+ 3,
815 ett_icmp_interface_info_object
,
816 c_type_fields
, ENC_BIG_ENDIAN
);
822 /*if ifIndex is set, next 32 bits are ifIndex */
824 proto_tree_add_item(ext_object_tree
, hf_icmp_int_info_index
, tvb
, offset
, 4, ENC_NA
);
828 /* IP Address Sub Object */
829 if (ipaddr_flag
&& (obj_end_offset
>= offset
+ 2)) {
830 /* Address Family Identifier */
831 afi
= tvb_get_ntohs(tvb
, offset
);
834 * if afi = 1, IPv4 address, 2 bytes afi, 2 bytes rsvd, 4 bytes IP addr
835 * if afi = 2, IPv6 address, 2 bytes afi, 2 bytes rsvd, 16 bytes IP addr
837 int_ipaddr_object_tree
= proto_tree_add_subtree(ext_object_tree
, tvb
, offset
,
838 afi
== 1 ? 8 : 20, ett_icmp_interface_ipaddr
, NULL
,
839 "IP Address Sub-Object");
841 proto_tree_add_uint(int_ipaddr_object_tree
,
842 hf_icmp_int_info_afi
, tvb
, offset
, 2,
846 proto_tree_add_item(int_ipaddr_object_tree
, hf_icmp_reserved
, tvb
, offset
, 2, ENC_NA
);
851 proto_tree_add_item(int_ipaddr_object_tree
, hf_icmp_int_info_ipv4
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
855 proto_tree_add_item(int_ipaddr_object_tree
, hf_icmp_int_info_ipv6
, tvb
, offset
, 16, ENC_NA
);
858 default: /* Unknown ?! */
859 proto_tree_add_item(int_ipaddr_object_tree
, hf_icmp_int_info_ipunknown
, tvb
, offset
, offset
- obj_end_offset
, ENC_NA
);
865 /* Interface Name Sub Object */
867 if (obj_end_offset
>= offset
+ 1) {
868 int_name_length
= tvb_get_uint8(tvb
, offset
);
869 int_name_object_tree
= proto_tree_add_subtree(ext_object_tree
, tvb
,
870 offset
, int_name_length
, ett_icmp_interface_name
, NULL
,
871 "Interface Name Sub-Object");
873 proto_tree_add_item(int_name_object_tree
, hf_icmp_int_info_name_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
876 if (obj_end_offset
>= offset
+ int_name_length
) {
877 proto_tree_add_item(int_name_object_tree
, hf_icmp_int_info_name_string
, tvb
, offset
, int_name_length
- 1, ENC_ASCII
);
878 offset
+= int_name_length
- 1;
883 proto_tree_add_item(ext_object_tree
, hf_icmp_int_info_mtu
, tvb
, offset
, 4, ENC_NA
);
887 return unknown_object
;
889 } /*end dissect_interface_information_object */
891 /* Dissect Interface Identification Object RFC 8335*/
893 dissect_interface_identification_object(tvbuff_t
* tvb
, int offset
,
894 proto_tree
* ext_object_tree
,
895 proto_item
* tf_object
)
902 uint32_t addr_length
;
904 unknown_object
= false;
906 obj_length
= tvb_get_ntohs(tvb
, offset
);
909 c_type
= tvb_get_uint8(tvb
, offset
+ 3);
911 proto_item_set_text(tf_object
, "Interface Identification Object");
912 if (tvb_reported_length_remaining(tvb
, offset
) < 5) {
913 /* Not enough room in the packet ! return unknown_object = true */
917 ti
= proto_tree_add_uint(ext_object_tree
, hf_icmp_ext_c_type
, tvb
, offset
+ 3, 1, c_type
);
918 proto_item_append_text(ti
, " (%s)", val_to_str(c_type
, ext_echo_ident_str
, "Unknown C-Type %u"));
922 case ICMP_EXT_ECHO_IDENT_NAME
:
923 proto_tree_add_item(ext_object_tree
, hf_icmp_int_ident_name_string
, tvb
, offset
, obj_length
- 4, ENC_ASCII
);
925 case ICMP_EXT_ECHO_IDENT_INDEX
:
926 proto_tree_add_item(ext_object_tree
, hf_icmp_int_ident_index
, tvb
, offset
, 4, ENC_NA
);
928 case ICMP_EXT_ECHO_IDENT_ADDRESS
:
929 proto_tree_add_item_ret_uint(ext_object_tree
, hf_icmp_int_ident_afi
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &afi
);
931 proto_tree_add_item_ret_uint(ext_object_tree
, hf_icmp_int_ident_addr_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &addr_length
);
933 proto_tree_add_item(ext_object_tree
, hf_icmp_int_ident_reserved
, tvb
, offset
, 1, ENC_NA
);
936 case AFNUM_INET
: /* IPv4 */
937 while(addr_length
>= 4 && tvb_reported_length_remaining(tvb
, offset
) >= 4) {
938 proto_tree_add_item(ext_object_tree
, hf_icmp_int_ident_ipv4
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
943 case AFNUM_INET6
: /* IPv6 */
944 while(addr_length
>= 16 && tvb_reported_length_remaining(tvb
, offset
) >= 16) {
945 proto_tree_add_item(ext_object_tree
, hf_icmp_int_ident_ipv6
, tvb
, offset
, 16, ENC_NA
);
950 default: /* Unknown ?! */
951 proto_tree_add_item(ext_object_tree
, hf_icmp_int_ident_address
, tvb
, offset
, tvb_reported_length_remaining(tvb
, offset
), ENC_NA
);
955 return unknown_object
;
957 } /*end dissect_interface_identification_object */
960 dissect_icmp_extension(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
)
966 uint16_t obj_length
, obj_trunc_length
, checksum
;
967 proto_item
*ti
, *tf_object
;
968 proto_tree
*ext_tree
, *ext_object_tree
;
970 unsigned reported_length
;
972 uint8_t int_info_obj_count
;
974 int_info_obj_count
= 0;
976 reported_length
= tvb_reported_length_remaining(tvb
, offset
);
978 /* Add a tree for multi-part extensions RFC 4884 */
979 ti
= proto_tree_add_none_format(tree
, hf_icmp_ext
, tvb
,
980 offset
, reported_length
,
981 "ICMP Multi-Part Extensions");
983 if (reported_length
< 4 /* Common header */ ) {
987 ext_tree
= proto_item_add_subtree(ti
, ett_icmp_ext
);
990 version
= hi_nibble(tvb_get_uint8(tvb
, offset
));
991 proto_tree_add_uint(ext_tree
, hf_icmp_ext_version
, tvb
, offset
, 1,
995 proto_tree_add_item(ext_tree
, hf_icmp_ext_reserved
,
996 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
999 checksum
= tvb_get_ntohs(tvb
, offset
+ 2);
1000 if (checksum
== 0) {
1001 proto_tree_add_checksum(ext_tree
, tvb
, offset
+ 2, hf_icmp_ext_checksum
, hf_icmp_ext_checksum_status
, &ei_icmp_ext_checksum
,
1002 pinfo
, 0, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NOT_PRESENT
);
1005 proto_tree_add_checksum(ext_tree
, tvb
, offset
+ 2, hf_icmp_ext_checksum
, hf_icmp_ext_checksum_status
, &ei_icmp_ext_checksum
,
1006 pinfo
, ip_checksum_tvb(tvb
, offset
, reported_length
), ENC_BIG_ENDIAN
, PROTO_CHECKSUM_VERIFY
|PROTO_CHECKSUM_IN_CKSUM
);
1009 if (version
!= 1 && version
!= 2) {
1010 /* Unsupported version */
1011 proto_item_append_text(ti
, " (unsupported version)");
1015 /* Skip the common header */
1018 /* While there is enough room to read an object */
1019 while (tvb_reported_length_remaining(tvb
, offset
) >=
1020 4 /* Object header */ ) {
1022 obj_length
= tvb_get_ntohs(tvb
, offset
);
1026 tvb_reported_length_remaining(tvb
, offset
));
1028 obj_end_offset
= offset
+ obj_trunc_length
;
1030 /* Add a subtree for this object (the text will be reset later) */
1031 ext_object_tree
= proto_tree_add_subtree(ext_tree
, tvb
, offset
,
1032 MAX(obj_trunc_length
, 4),
1033 ett_icmp_ext_object
, &tf_object
, "Unknown object");
1035 proto_tree_add_uint(ext_object_tree
, hf_icmp_ext_length
,
1036 tvb
, offset
, 2, obj_length
);
1039 class_num
= tvb_get_uint8(tvb
, offset
+ 2);
1040 proto_tree_add_item(ext_object_tree
, hf_icmp_ext_class
,
1041 tvb
, offset
+ 2, 1, ENC_BIG_ENDIAN
);
1044 c_type
= tvb_get_uint8(tvb
, offset
+ 3);
1046 if (obj_length
< 4 /* Object header */ ) {
1047 /* Thanks doc/README.developer :)) */
1048 proto_item_set_text(tf_object
,
1049 "Object with bad length");
1054 switch (class_num
) {
1055 case MPLS_STACK_ENTRY_OBJECT_CLASS
:
1057 dissect_mpls_stack_entry_object(tvb
, offset
,
1061 case INTERFACE_INFORMATION_OBJECT_CLASS
:
1063 dissect_interface_information_object(tvb
,
1067 int_info_obj_count
++;
1068 if (int_info_obj_count
> 4) {
1069 proto_item_set_text(tf_object
,
1070 "More than 4 Interface Information Objects");
1073 case MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS
:
1075 dissect_mpls_extended_payload_object(tvb
,
1080 case INTERFACE_IDENTIFICATION_OBJECT_CLASS
:
1082 dissect_interface_identification_object(tvb
,
1089 unknown_object
= true;
1092 } /* end switch class_num */
1094 /* The switches couldn't decode the object */
1095 if (unknown_object
== true) {
1096 proto_tree_add_item(ext_object_tree
, hf_icmp_ext_c_type
, tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
1098 /* Skip the object header */
1101 proto_item_set_text(tf_object
,
1102 "Unknown object (%d/%d)",
1105 if (obj_trunc_length
> 4) {
1106 proto_tree_add_item(ext_object_tree
, hf_icmp_ext_data
, tvb
, offset
, obj_trunc_length
- 4, ENC_NA
);
1111 if (obj_trunc_length
< obj_length
) {
1112 proto_item_append_text(tf_object
, " (truncated)");
1115 /* Go to the end of the object */
1116 offset
= obj_end_offset
;
1122 /* ======================================================================= */
1124 Note: We are tracking conversations via these keys:
1127 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
1128 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1130 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1131 | Identifier | Sequence Number |
1132 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1134 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1136 static icmp_transaction_t
*transaction_start(packet_info
* pinfo
,
1140 conversation_t
*conversation
;
1141 icmp_conv_info_t
*icmp_info
;
1142 icmp_transaction_t
*icmp_trans
;
1143 wmem_tree_key_t icmp_key
[3];
1146 /* Handle the conversation tracking */
1147 conversation
= _find_or_create_conversation(pinfo
);
1148 icmp_info
= (icmp_conv_info_t
*)conversation_get_proto_data(conversation
, proto_icmp
);
1149 if (icmp_info
== NULL
) {
1150 icmp_info
= wmem_new(wmem_file_scope(), icmp_conv_info_t
);
1151 icmp_info
->unmatched_pdus
= wmem_tree_new(wmem_file_scope());
1152 icmp_info
->matched_pdus
= wmem_tree_new(wmem_file_scope());
1153 conversation_add_proto_data(conversation
, proto_icmp
,
1157 if (!PINFO_FD_VISITED(pinfo
)) {
1158 /* this is a new request, create a new transaction structure and map it to the
1161 icmp_key
[0].length
= 3;
1162 icmp_key
[0].key
= key
;
1163 icmp_key
[1].length
= 0;
1164 icmp_key
[1].key
= NULL
;
1166 icmp_trans
= wmem_new(wmem_file_scope(), icmp_transaction_t
);
1167 icmp_trans
->rqst_frame
= pinfo
->num
;
1168 icmp_trans
->resp_frame
= 0;
1169 icmp_trans
->rqst_time
= pinfo
->abs_ts
;
1170 nstime_set_zero(&icmp_trans
->resp_time
);
1171 wmem_tree_insert32_array(icmp_info
->unmatched_pdus
, icmp_key
,
1172 (void *) icmp_trans
);
1174 /* Already visited this frame */
1175 uint32_t frame_num
= pinfo
->num
;
1177 icmp_key
[0].length
= 3;
1178 icmp_key
[0].key
= key
;
1179 icmp_key
[1].length
= 1;
1180 icmp_key
[1].key
= &frame_num
;
1181 icmp_key
[2].length
= 0;
1182 icmp_key
[2].key
= NULL
;
1185 (icmp_transaction_t
*)wmem_tree_lookup32_array(icmp_info
->matched_pdus
,
1188 if (icmp_trans
== NULL
) {
1189 if (ADDR_IS_NOT_UNICAST(&pinfo
->dst
)) {
1190 /* Note the non-unicast destination and skip transaction tracking */
1191 col_append_str(pinfo
->cinfo
, COL_INFO
, ADDR_IS_BROADCAST(&pinfo
->dst
) ? " (broadcast)" : " (multicast)");
1192 } else if (PINFO_FD_VISITED(pinfo
)) {
1193 /* No response found - add field and expert info */
1194 it
= proto_tree_add_item(tree
, hf_icmp_no_resp
, NULL
, 0, 0,
1196 proto_item_set_generated(it
);
1198 col_append_str(pinfo
->cinfo
, COL_INFO
, " (no response found!)");
1200 /* Expert info. TODO: add to _icmp_transaction_t type and sequence number
1201 so can report here (and in taps) */
1202 expert_add_info_format(pinfo
, it
, &ei_icmp_resp_not_found
,
1203 "No response seen to ICMP request");
1209 /* Print state tracking in the tree */
1210 if (icmp_trans
->resp_frame
) {
1211 it
= proto_tree_add_uint(tree
, hf_icmp_resp_in
, NULL
, 0, 0,
1212 icmp_trans
->resp_frame
);
1213 proto_item_set_generated(it
);
1215 col_append_frame_number(pinfo
, COL_INFO
, " (reply in %u)",
1216 icmp_trans
->resp_frame
);
1221 } /* transaction_start() */
1223 /* ======================================================================= */
1224 static icmp_transaction_t
*transaction_end(packet_info
* pinfo
,
1228 conversation_t
*conversation
;
1229 icmp_conv_info_t
*icmp_info
;
1230 icmp_transaction_t
*icmp_trans
;
1231 wmem_tree_key_t icmp_key
[3];
1237 find_conversation(pinfo
->num
, &pinfo
->src
, &pinfo
->dst
,
1238 conversation_pt_to_conversation_type(pinfo
->ptype
), 0, 0, 0);
1239 if (conversation
== NULL
) {
1243 icmp_info
= (icmp_conv_info_t
*)conversation_get_proto_data(conversation
, proto_icmp
);
1244 if (icmp_info
== NULL
) {
1248 if (!PINFO_FD_VISITED(pinfo
)) {
1251 icmp_key
[0].length
= 3;
1252 icmp_key
[0].key
= key
;
1253 icmp_key
[1].length
= 0;
1254 icmp_key
[1].key
= NULL
;
1256 (icmp_transaction_t
*)wmem_tree_lookup32_array(icmp_info
->unmatched_pdus
,
1258 if (icmp_trans
== NULL
) {
1262 /* we have already seen this response, or an identical one */
1263 if (icmp_trans
->resp_frame
!= 0) {
1267 icmp_trans
->resp_frame
= pinfo
->num
;
1269 /* we found a match. Add entries to the matched table for both request and reply frames
1271 icmp_key
[0].length
= 3;
1272 icmp_key
[0].key
= key
;
1273 icmp_key
[1].length
= 1;
1274 icmp_key
[1].key
= &frame_num
;
1275 icmp_key
[2].length
= 0;
1276 icmp_key
[2].key
= NULL
;
1278 frame_num
= icmp_trans
->rqst_frame
;
1279 wmem_tree_insert32_array(icmp_info
->matched_pdus
, icmp_key
,
1280 (void *) icmp_trans
);
1282 frame_num
= icmp_trans
->resp_frame
;
1283 wmem_tree_insert32_array(icmp_info
->matched_pdus
, icmp_key
,
1284 (void *) icmp_trans
);
1286 /* Already visited this frame */
1287 uint32_t frame_num
= pinfo
->num
;
1289 icmp_key
[0].length
= 3;
1290 icmp_key
[0].key
= key
;
1291 icmp_key
[1].length
= 1;
1292 icmp_key
[1].key
= &frame_num
;
1293 icmp_key
[2].length
= 0;
1294 icmp_key
[2].key
= NULL
;
1297 (icmp_transaction_t
*)wmem_tree_lookup32_array(icmp_info
->matched_pdus
,
1300 if (icmp_trans
== NULL
) {
1306 it
= proto_tree_add_uint(tree
, hf_icmp_resp_to
, NULL
, 0, 0,
1307 icmp_trans
->rqst_frame
);
1308 proto_item_set_generated(it
);
1310 nstime_delta(&ns
, &pinfo
->abs_ts
, &icmp_trans
->rqst_time
);
1311 icmp_trans
->resp_time
= ns
;
1312 resp_time
= nstime_to_msec(&ns
);
1313 it
= proto_tree_add_double_format_value(tree
, hf_icmp_resptime
,
1314 NULL
, 0, 0, resp_time
,
1315 "%.3f ms", resp_time
);
1316 proto_item_set_generated(it
);
1318 col_append_frame_number(pinfo
, COL_INFO
, " (request in %d)",
1319 icmp_trans
->rqst_frame
);
1323 } /* transaction_end() */
1326 update_best_guess_timestamp(time_t secs
, int64_t usecs
, const nstime_t
*comp_ts
, nstime_t
*out_ts
, nstime_t
*best_diff
)
1329 if (usecs
< 1000000 && usecs
>= 0) {
1330 /* suseconds_t allows -1 but we'll reject it */
1332 ts
.nsecs
= (int)(1000 * usecs
);
1333 (nstime_cmp(comp_ts
, &ts
) > 0) ? nstime_delta(&delta
, comp_ts
, &ts
) : nstime_delta(&delta
, &ts
, comp_ts
);
1334 if (nstime_cmp(&delta
, best_diff
) < 0) {
1335 nstime_copy(best_diff
, &delta
);
1336 nstime_copy(out_ts
, &ts
);
1344 get_best_guess_timestamp(tvbuff_t
*tvb
, int offset
, nstime_t
*comp_ts
, nstime_t
*out_ts
)
1346 /* Mike Muuss's original ping program put a timeval in the first
1347 * 8 bytes. Many (most?) implementations follow this, but as it's
1348 * not in the RFCs, it's usually just sent in native byte order.
1349 * Modern systems have 64 bit time_t, so we'll check that too.
1350 * The heuristic is to assume the value that has the smallest
1351 * absolute difference with the given time (the frame timestamp),
1352 * so long as it's less than a maximum value.
1354 * XXX: There are other possibilities. A system could use a 32 bit
1355 * suseconds_t even with a 64 bit time_t (as our nstime_t does with
1356 * nsecs on platforms with a 32 bit int, and as NetBSD and OpenBSD
1357 * apparently do) and other implementations of ping could do whatever
1358 * they want (e.g., send a timespec with with nanosecond fractional
1362 if (!tvb_bytes_exist(tvb
, offset
, 8)) {
1366 /* Maximum delta we'll accept. We've been using one day for well over
1367 * a decade; it could be tighter, but I suppose this helps for captures
1368 * made on machines that didn't have their timezones set correctly?
1370 nstime_t best_delta
= NSTIME_INIT_SECS(3600 * 24);
1371 int64_t secs
, usecs
;
1374 if (tvb_bytes_exist(tvb
, offset
, 16)) {
1375 /* LE timeval, 64 bit time_t */
1376 secs
= (time_t)tvb_get_letoh64(tvb
, offset
);
1377 usecs
= tvb_get_letoh64(tvb
, offset
+ 8);
1378 if (update_best_guess_timestamp(secs
, usecs
, comp_ts
, out_ts
, &best_delta
)) {
1383 /* LE timeval, 32 bit time_t */
1384 secs
= tvb_get_letohl(tvb
, offset
);
1385 usecs
= tvb_get_letohl(tvb
, offset
+ 4);
1386 /* Pre-Y2038, a timeval with 64 bit time_t looks like a LE timeval with
1387 * 32 bit time_t and 0 fractional seconds. Assume that (with legal
1388 * value for the following 64 bit usecs) is less likely than clock skew
1389 * that makes the ping timestamp in the future, and avoid the wrong
1390 * decision in the latter case. */
1391 if (len
== 0 || usecs
!= 0) {
1392 if (update_best_guess_timestamp(secs
, usecs
, comp_ts
, out_ts
, &best_delta
)) {
1397 /* BE timeval, 32 bit time_t */
1398 secs
= tvb_get_ntohl(tvb
, offset
);
1399 usecs
= tvb_get_ntohl(tvb
, offset
+ 4);
1400 if (update_best_guess_timestamp(secs
, usecs
, comp_ts
, out_ts
, &best_delta
)) {
1404 if (tvb_bytes_exist(tvb
, offset
, 16)) {
1405 /* BE timeval, 64 bit time_t */
1406 secs
= (time_t)tvb_get_ntoh64(tvb
, offset
);
1407 usecs
= tvb_get_ntoh64(tvb
, offset
+ 8);
1408 if (update_best_guess_timestamp(secs
, usecs
, comp_ts
, out_ts
, &best_delta
)) {
1416 #define MSPERDAY 86400000
1418 /* ======================================================================= */
1420 get_best_guess_mstimeofday(tvbuff_t
* tvb
, int offset
, uint32_t comp_ts
)
1422 uint32_t be_ts
, le_ts
;
1424 /* Account for the special case from RFC 792 as best we can by clearing
1425 * the msb. Ref: [Page 16] of https://tools.ietf.org/html/rfc792:
1427 If the time is not available in milliseconds or cannot be provided
1428 with respect to midnight UT then any time can be inserted in a
1429 timestamp provided the high order bit of the timestamp is also set
1430 to indicate this non-standard value.
1432 be_ts
= tvb_get_ntohl(tvb
, offset
) & 0x7fffffff;
1433 le_ts
= tvb_get_letohl(tvb
, offset
) & 0x7fffffff;
1435 if (be_ts
< MSPERDAY
&& le_ts
>= MSPERDAY
) {
1439 if (le_ts
< MSPERDAY
&& be_ts
>= MSPERDAY
) {
1443 if (be_ts
< MSPERDAY
&& le_ts
< MSPERDAY
) {
1444 uint32_t saved_be_ts
= be_ts
;
1445 uint32_t saved_le_ts
= le_ts
;
1447 /* Is this a rollover to a new day, clocks not synchronized, different
1448 * timezones between originate and receive/transmit, .. what??? */
1449 if (be_ts
< comp_ts
&& be_ts
<= (MSPERDAY
/ 4)
1450 && comp_ts
>= (MSPERDAY
- (MSPERDAY
/ 4)))
1451 be_ts
+= MSPERDAY
; /* Assume a rollover to a new day */
1452 if (le_ts
< comp_ts
&& le_ts
<= (MSPERDAY
/ 4)
1453 && comp_ts
>= (MSPERDAY
- (MSPERDAY
/ 4)))
1454 le_ts
+= MSPERDAY
; /* Assume a rollover to a new day */
1455 if ((be_ts
- comp_ts
) < (le_ts
- comp_ts
))
1460 /* Both are bigger than MSPERDAY, but neither one's msb's are set. This
1461 * is clearly invalid, but now what TODO? For now, take the one closest to
1462 * the comparative timestamp, which is another way of saying, "let's
1463 * return a deterministic wild guess. */
1464 if ((be_ts
- comp_ts
) < (le_ts
- comp_ts
)) {
1468 } /* get_best_guess_mstimeofday() */
1471 capture_icmp(const unsigned char *pd _U_
, int offset _U_
, int len _U_
, capture_packet_info_t
*cpinfo
, const union wtap_pseudo_header
*pseudo_header _U_
)
1473 capture_dissector_increment_count(cpinfo
, proto_icmp
);
1478 * RFC 792 for basic ICMP.
1479 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1480 * RFC 1256 for router discovery messages.
1481 * RFC 2002 and 3012 for Mobile IP stuff.
1484 dissect_icmp(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data
)
1486 proto_tree
*icmp_tree
= NULL
;
1487 proto_item
*ti
, *checksum_item
;
1490 uint8_t icmp_original_dgram_length
;
1491 unsigned captured_length
, reported_length
;
1492 const char *type_str
, *code_str
;
1493 uint32_t num_addrs
= 0;
1494 uint32_t addr_entry_size
= 0;
1496 bool save_in_error_pkt
;
1498 uint32_t conv_key
[3];
1499 icmp_transaction_t
*trans
= NULL
;
1500 nstime_t ts
, time_relative
;
1501 ws_ip4
*iph
= WS_IP4_PTR(data
);
1503 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ICMP");
1504 col_clear(pinfo
->cinfo
, COL_INFO
);
1506 /* To do: check for runts, errs, etc. */
1507 icmp_type
= tvb_get_uint8(tvb
, 0);
1508 icmp_code
= tvb_get_uint8(tvb
, 1);
1509 /* RFC 4884: Length of original datagram carried in the ICMP payload,
1510 * or 0 otherwise. Length in terms of 32 bit words.*/
1511 icmp_original_dgram_length
= tvb_get_uint8(tvb
, 5);
1514 val_to_str_const(icmp_type
, icmp_type_str
,
1515 "Unknown ICMP (obsolete or malformed?)");
1517 switch (icmp_type
) {
1520 val_to_str(icmp_code
, unreach_code_str
,
1521 "Unknown code: %u");
1525 val_to_str(icmp_code
, redir_code_str
,
1526 "Unknown code: %u");
1530 val_to_str(icmp_code
, alt_host_code_str
,
1531 "Unknown code: %u");
1532 icmp_original_dgram_length
= 0;
1534 case ICMP_RTRADVERT
:
1535 switch (icmp_code
) {
1536 case 0: /* Mobile-Ip */
1537 case 16: /* Mobile-Ip */
1538 type_str
= "Mobile IP Advertisement";
1540 } /* switch icmp_code */
1542 val_to_str(icmp_code
, rtradvert_code_str
,
1543 "Unknown code: %u");
1547 val_to_str(icmp_code
, ttl_code_str
,
1548 "Unknown code: %u");
1550 case ICMP_PARAMPROB
:
1552 val_to_str(icmp_code
, par_code_str
,
1553 "Unknown code: %u");
1557 val_to_str(icmp_code
, photuris_code_str
,
1558 "Unknown code: %u");
1562 val_to_str(icmp_code
, ext_echo_req_code_str
,
1563 "Unknown code: %u");
1565 case ICMP_EXTECHOREPLY
:
1567 val_to_str(icmp_code
, ext_echo_reply_code_str
,
1568 "Unknown code: %u");
1575 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%-20s", type_str
);
1577 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s)", code_str
);
1580 captured_length
= tvb_captured_length(tvb
);
1581 reported_length
= tvb_reported_length(tvb
);
1583 ti
= proto_tree_add_item(tree
, proto_icmp
, tvb
, 0, captured_length
, ENC_NA
);
1584 icmp_tree
= proto_item_add_subtree(ti
, ett_icmp
);
1586 ti
= proto_tree_add_item(icmp_tree
, hf_icmp_type
, tvb
, 0, 1,
1588 proto_item_append_text(ti
, " (%s)", type_str
);
1589 switch (icmp_type
) {
1590 case ICMP_SOURCEQUENCH
:
1593 case ICMP_IREQREPLY
:
1595 case ICMP_MASKREPLY
:
1606 expert_add_info(pinfo
, ti
, &ei_icmp_type_deprecated
);
1612 ti
= proto_tree_add_item(icmp_tree
, hf_icmp_code
, tvb
, 1, 1,
1615 proto_item_append_text(ti
, " (%s)", code_str
);
1618 if (!pinfo
->fragmented
&& captured_length
>= reported_length
1619 && !pinfo
->flags
.in_error_pkt
) {
1620 /* The packet isn't part of a fragmented datagram, isn't
1621 truncated, and isn't the payload of an error packet, so we can checksum
1623 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
),
1624 ENC_BIG_ENDIAN
, PROTO_CHECKSUM_VERIFY
|PROTO_CHECKSUM_IN_CKSUM
);
1626 checksum_item
= proto_tree_add_checksum(icmp_tree
, tvb
, 2, hf_icmp_checksum
, hf_icmp_checksum_status
, &ei_icmp_checksum
, pinfo
, 0,
1627 ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
1628 proto_item_append_text(checksum_item
, " [%s]",
1629 pinfo
->flags
.in_error_pkt
? "in ICMP error packet" : "fragmented datagram");
1632 /* Decode the second 4 bytes of the packet. */
1633 switch (icmp_type
) {
1634 case ICMP_ECHOREPLY
:
1637 case ICMP_TSTAMPREPLY
:
1639 case ICMP_IREQREPLY
:
1641 case ICMP_MASKREPLY
:
1642 proto_tree_add_item(icmp_tree
, hf_icmp_ident
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
1643 proto_tree_add_item(icmp_tree
, hf_icmp_ident_le
, tvb
, 4, 2, ENC_LITTLE_ENDIAN
);
1644 proto_tree_add_item(icmp_tree
, hf_icmp_seq_num
, tvb
, 6, 2, ENC_BIG_ENDIAN
);
1645 proto_tree_add_item(icmp_tree
, hf_icmp_seq_num_le
, tvb
, 6, 2, ENC_LITTLE_ENDIAN
);
1646 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " id=0x%04x, seq=%u/%u",
1647 tvb_get_ntohs(tvb
, 4), tvb_get_ntohs(tvb
, 6), tvb_get_letohs(tvb
, 6));
1649 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", ttl=%u", iph
->ip_ttl
);
1654 if (icmp_original_dgram_length
> 0) {
1655 proto_tree_add_item(icmp_tree
, hf_icmp_unused
, tvb
, 4, 1, ENC_NA
);
1656 proto_tree_add_item(icmp_tree
, hf_icmp_length
, tvb
, 5, 1, ENC_BIG_ENDIAN
);
1657 ti
= proto_tree_add_uint(icmp_tree
, hf_icmp_length_original_datagram
,
1658 tvb
, 5, 1, icmp_original_dgram_length
* 4);
1659 proto_item_set_generated(ti
);
1660 if (icmp_code
== ICMP_FRAG_NEEDED
) {
1661 proto_tree_add_item(icmp_tree
, hf_icmp_mtu
, tvb
, 6, 2, ENC_BIG_ENDIAN
);
1663 proto_tree_add_item(icmp_tree
, hf_icmp_unused
, tvb
, 6, 2, ENC_NA
);
1665 } else if (icmp_code
== ICMP_FRAG_NEEDED
) {
1666 proto_tree_add_item(icmp_tree
, hf_icmp_unused
, tvb
, 4, 2, ENC_NA
);
1667 proto_tree_add_item(icmp_tree
, hf_icmp_mtu
, tvb
, 6, 2, ENC_BIG_ENDIAN
);
1669 proto_tree_add_item(icmp_tree
, hf_icmp_unused
, tvb
, 4, 4, ENC_NA
);
1673 case ICMP_RTRADVERT
:
1674 proto_tree_add_item_ret_uint(icmp_tree
, hf_icmp_num_addrs
, tvb
, 4, 1, ENC_BIG_ENDIAN
, &num_addrs
);
1675 proto_tree_add_item_ret_uint(icmp_tree
, hf_icmp_addr_entry_size
, tvb
, 5, 1, ENC_BIG_ENDIAN
, &addr_entry_size
);
1676 ti
= proto_tree_add_item(icmp_tree
, hf_icmp_lifetime
, tvb
, 6, 2, ENC_BIG_ENDIAN
);
1677 proto_item_append_text(ti
, " (%s)", signed_time_secs_to_str(pinfo
->pool
, tvb_get_ntohs(tvb
, 6)));
1680 case ICMP_PARAMPROB
:
1681 proto_tree_add_item(icmp_tree
, hf_icmp_pointer
, tvb
, 4, 1, ENC_BIG_ENDIAN
);
1682 if (icmp_original_dgram_length
> 0) {
1683 proto_tree_add_item(icmp_tree
, hf_icmp_length
, tvb
, 5, 1, ENC_BIG_ENDIAN
);
1684 ti
= proto_tree_add_uint(icmp_tree
, hf_icmp_length_original_datagram
,
1685 tvb
, 5, 1, icmp_original_dgram_length
* 4);
1686 proto_item_set_generated(ti
);
1687 proto_tree_add_item(icmp_tree
, hf_icmp_unused
, tvb
, 6, 2, ENC_NA
);
1689 proto_tree_add_item(icmp_tree
, hf_icmp_unused
, tvb
, 5, 3, ENC_NA
);
1694 proto_tree_add_item(icmp_tree
, hf_icmp_redir_gw
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1698 if (icmp_original_dgram_length
> 0) {
1699 proto_tree_add_item(icmp_tree
, hf_icmp_unused
, tvb
, 4, 1, ENC_NA
);
1700 proto_tree_add_item(icmp_tree
, hf_icmp_length
, tvb
, 5, 1, ENC_BIG_ENDIAN
);
1701 ti
= proto_tree_add_uint(icmp_tree
, hf_icmp_length_original_datagram
,
1702 tvb
, 5, 1, icmp_original_dgram_length
* 4);
1703 proto_item_set_generated(ti
);
1704 proto_tree_add_item(icmp_tree
, hf_icmp_unused
, tvb
, 6, 2, ENC_NA
);
1706 proto_tree_add_item(icmp_tree
, hf_icmp_unused
, tvb
, 4, 4, ENC_NA
);
1711 proto_tree_add_item(icmp_tree
, hf_icmp_ident
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
1712 proto_tree_add_item(icmp_tree
, hf_icmp_ident_le
, tvb
, 4, 2, ENC_LITTLE_ENDIAN
);
1713 proto_tree_add_item(icmp_tree
, hf_icmp_ext_echo_seq_num
, tvb
, 6, 1, ENC_BIG_ENDIAN
);
1714 proto_tree_add_item(icmp_tree
, hf_icmp_ext_echo_req_reserved
, tvb
, 7, 1, ENC_BIG_ENDIAN
);
1715 proto_tree_add_item(icmp_tree
, hf_icmp_ext_echo_req_local
, tvb
, 7, 1, ENC_BIG_ENDIAN
);
1718 case ICMP_EXTECHOREPLY
:
1719 proto_tree_add_item(icmp_tree
, hf_icmp_ident
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
1720 proto_tree_add_item(icmp_tree
, hf_icmp_ident_le
, tvb
, 4, 2, ENC_LITTLE_ENDIAN
);
1721 proto_tree_add_item(icmp_tree
, hf_icmp_ext_echo_seq_num
, tvb
, 6, 1, ENC_BIG_ENDIAN
);
1722 proto_tree_add_item(icmp_tree
, hf_icmp_ext_echo_rsp_state
, tvb
, 7, 1, ENC_BIG_ENDIAN
);
1723 proto_tree_add_item(icmp_tree
, hf_icmp_ext_echo_rsp_reserved
, tvb
, 7, 1, ENC_BIG_ENDIAN
);
1724 proto_tree_add_item(icmp_tree
, hf_icmp_ext_echo_rsp_active
, tvb
, 7, 1, ENC_BIG_ENDIAN
);
1725 proto_tree_add_item(icmp_tree
, hf_icmp_ext_echo_rsp_ipv4
, tvb
, 7, 1, ENC_BIG_ENDIAN
);
1726 proto_tree_add_item(icmp_tree
, hf_icmp_ext_echo_rsp_ipv6
, tvb
, 7, 1, ENC_BIG_ENDIAN
);
1731 /* Decode the additional information in the packet. */
1732 switch (icmp_type
) {
1735 case ICMP_PARAMPROB
:
1736 case ICMP_SOURCEQUENCH
:
1738 /* Save the current value of the "we're inside an error packet"
1739 flag, and set that flag; subdissectors may treat packets
1740 that are the payload of error packets differently from
1742 save_in_error_pkt
= pinfo
->flags
.in_error_pkt
;
1743 pinfo
->flags
.in_error_pkt
= true;
1745 /* Decode the IP header and first 64 bits of data from the
1746 original datagram. */
1747 next_tvb
= tvb_new_subset_remaining(tvb
, 8);
1749 /* If the packet is compliant with RFC 4884, then it has
1750 * icmp_original_dgram_length*4 bytes of original IP packet that needs
1751 * to be decoded, followed by extension objects.
1754 if (icmp_type
== ICMP_REDIRECT
) {
1755 /* No icmp_original_dgram_length is available for redirect message,
1756 * we expect a max of Internet Header + 64 bits of Original Data Datagram */
1757 set_actual_length(next_tvb
, ((tvb_get_uint8(tvb
, 8) & 0x0f) * 4) + 8);
1758 } else if (icmp_original_dgram_length
1759 && (tvb_reported_length(tvb
) >
1760 (unsigned) (8 + icmp_original_dgram_length
* 4))
1761 && (tvb_get_ntohs(tvb
, 8 + 2) >
1762 (unsigned) icmp_original_dgram_length
* 4)) {
1763 set_actual_length(next_tvb
,
1764 ((tvb_get_uint8(tvb
, 8) & 0x0f) + icmp_original_dgram_length
) * 4);
1766 /* There is a collision between RFC 1812 and draft-ietf-mpls-icmp-02.
1767 We don't know how to decode the 128th and following bytes of the ICMP payload.
1768 According to draft-ietf-mpls-icmp-02, these bytes should be decoded as MPLS extensions
1769 whereas RFC 1812 tells us to decode them as a portion of the original packet.
1770 Let the user decide.
1772 Here the user decided to favor MPLS extensions.
1773 Force the IP dissector to decode only the first 128 bytes. */
1774 if ((tvb_reported_length(tvb
) > 8 + 128) &&
1776 && (tvb_get_ntohs(tvb
, 8 + 2) > 128)) {
1777 set_actual_length(next_tvb
, 128);
1781 call_dissector(ip_handle
, next_tvb
, pinfo
, icmp_tree
);
1783 /* Restore the "we're inside an error packet" flag. */
1784 pinfo
->flags
.in_error_pkt
= save_in_error_pkt
;
1786 /* Decode MPLS extensions if the payload has at least 128 bytes, and
1787 - the original packet in the ICMP payload has less than 128 bytes, or
1788 - the user favors the MPLS extensions analysis */
1789 if ((tvb_reported_length(tvb
) > 8 + 128)
1790 && (tvb_get_ntohs(tvb
, 8 + 2) <= 128
1791 || favor_icmp_mpls_ext
)) {
1792 int ext_offset
= MAX(icmp_original_dgram_length
* 4, 128) + 8;
1793 tvbuff_t
* extension_tvb
= tvb_new_subset_remaining(tvb
, ext_offset
);
1794 dissect_icmp_extension(extension_tvb
, pinfo
, icmp_tree
, NULL
);
1797 case ICMP_ECHOREPLY
:
1799 if (icmp_type
== ICMP_ECHOREPLY
) {
1800 if (!pinfo
->flags
.in_error_pkt
) {
1802 (uint32_t) tvb_get_ntohs(tvb
, 2);
1803 if (conv_key
[0] == 0xffff) {
1806 if (pinfo
->flags
.in_gre_pkt
&& prefs
.strict_conversation_tracking_heuristics
)
1807 conv_key
[0] |= 0x00010000; /* set a bit for "in GRE" */
1809 ((uint32_t) tvb_get_ntohs(tvb
, 4) << 16) |
1810 tvb_get_ntohs(tvb
, 6);
1811 conv_key
[2] = prefs
.strict_conversation_tracking_heuristics
? pinfo
->vlan_id
: 0;
1813 transaction_end(pinfo
, icmp_tree
,
1817 if (!pinfo
->flags
.in_error_pkt
) {
1820 tmp
[0] = ~tvb_get_ntohs(tvb
, 2);
1821 tmp
[1] = ~0x0800; /* The difference between echo request & reply */
1823 ip_checksum((uint8_t *) & tmp
,
1825 if (pinfo
->flags
.in_gre_pkt
&& prefs
.strict_conversation_tracking_heuristics
) {
1826 conv_key
[0] |= 0x00010000; /* set a bit for "in GRE" */
1829 ((uint32_t) tvb_get_ntohs(tvb
, 4) << 16) |
1830 tvb_get_ntohs(tvb
, 6);
1831 conv_key
[2] = prefs
.strict_conversation_tracking_heuristics
? pinfo
->vlan_id
: 0;
1833 transaction_start(pinfo
, icmp_tree
,
1838 /* Make sure we have enough bytes in the payload before trying to
1839 * see if the data looks like a timestamp; otherwise we'll get
1840 * malformed packets as we try to access data that isn't there. */
1841 if (tvb_captured_length_remaining(tvb
, 8) < 8) {
1842 if (tvb_captured_length_remaining(tvb
, 8) > 0) {
1843 call_data_dissector(tvb_new_subset_remaining
1844 (tvb
, 8), pinfo
, icmp_tree
);
1849 /* Interpret the first 8 or 16 bytes of the icmp data as a timestamp
1850 * But only if it does look like it's a timestamp.
1853 int len
= get_best_guess_timestamp(tvb
, 8, &pinfo
->abs_ts
, &ts
);
1855 proto_tree_add_time(icmp_tree
, hf_icmp_data_time
,
1857 nstime_delta(&time_relative
, &pinfo
->abs_ts
,
1859 ti
= proto_tree_add_time(icmp_tree
,
1860 hf_icmp_data_time_relative
,
1863 proto_item_set_generated(ti
);
1864 call_data_dissector(tvb_new_subset_remaining(tvb
,
1868 heur_dtbl_entry_t
*hdtbl_entry
;
1869 next_tvb
= tvb_new_subset_remaining(tvb
, 8);
1870 if (!dissector_try_heuristic(icmp_heur_subdissector_list
, next_tvb
, pinfo
, tree
, &hdtbl_entry
, NULL
)) {
1871 call_data_dissector(next_tvb
, pinfo
, icmp_tree
);
1876 case ICMP_RTRADVERT
:
1877 if (addr_entry_size
== 2) {
1878 for (i
= 0; i
< num_addrs
; i
++) {
1879 proto_tree_add_item(icmp_tree
, hf_icmp_router_address
, tvb
, 8 + (i
* 8), 4, ENC_NA
);
1880 proto_tree_add_item(icmp_tree
, hf_icmp_pref_level
, tvb
, 12 + (i
* 8), 4, ENC_NA
);
1882 if ((icmp_code
== 0) || (icmp_code
== 16)) {
1884 dissect_mip_extensions(tvb
, 8 + i
* 8,
1888 call_data_dissector(tvb_new_subset_remaining(tvb
, 8),
1894 case ICMP_TSTAMPREPLY
:
1896 uint32_t frame_ts
, orig_ts
;
1898 frame_ts
= (uint32_t)(((pinfo
->abs_ts
.secs
* 1000) +
1899 (pinfo
->abs_ts
.nsecs
/ 1000000)) %
1902 orig_ts
= get_best_guess_mstimeofday(tvb
, 8, frame_ts
);
1903 ti
= proto_tree_add_item(icmp_tree
, hf_icmp_originate_timestamp
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1904 proto_item_append_text(ti
, " (%s after midnight UTC)", signed_time_msecs_to_str(pinfo
->pool
, orig_ts
));
1906 ti
= proto_tree_add_item(icmp_tree
, hf_icmp_receive_timestamp
, tvb
, 12, 4, ENC_BIG_ENDIAN
);
1907 proto_item_append_text(ti
, " (%s after midnight UTC)", signed_time_msecs_to_str(pinfo
->pool
, get_best_guess_mstimeofday(tvb
, 12, frame_ts
)));
1909 ti
= proto_tree_add_item(icmp_tree
, hf_icmp_transmit_timestamp
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1910 proto_item_append_text(ti
, " (%s after midnight UTC)", signed_time_msecs_to_str(pinfo
->pool
, get_best_guess_mstimeofday(tvb
, 16, frame_ts
)));
1916 case ICMP_MASKREPLY
:
1917 proto_tree_add_item(icmp_tree
, hf_icmp_address_mask
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1921 if (tvb_reported_length(tvb
) > 8) {
1922 tvbuff_t
* extension_tvb
= tvb_new_subset_remaining(tvb
, 8);
1923 dissect_icmp_extension(extension_tvb
, pinfo
, icmp_tree
, NULL
);
1928 if (!PINFO_FD_VISITED(pinfo
)) {
1929 icmp_info_t
*p_icmp_info
= wmem_new(wmem_file_scope(), icmp_info_t
);
1930 p_icmp_info
->type
= icmp_type
;
1931 p_icmp_info
->code
= icmp_code
;
1932 p_add_proto_data(wmem_file_scope(), pinfo
, proto_icmp
, 0, p_icmp_info
);
1936 tap_queue_packet(icmp_tap
, pinfo
, trans
);
1939 return tvb_reported_length(tvb
);
1942 void proto_register_icmp(void)
1944 static hf_register_info hf
[] = {
1946 {"Type", "icmp.type", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1950 {"Code", "icmp.code", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1954 {"Checksum", "icmp.checksum", FT_UINT16
, BASE_HEX
, NULL
,
1958 {&hf_icmp_checksum_status
,
1959 {"Checksum Status", "icmp.checksum.status", FT_UINT8
, BASE_NONE
,
1960 VALS(proto_checksum_vals
), 0x0,
1964 {"Unused", "icmp.unused", FT_BYTES
,
1965 BASE_NONE
, NULL
, 0x0,
1969 {"Reserved", "icmp.reserved", FT_BYTES
,
1970 BASE_NONE
, NULL
, 0x0,
1974 {"Identifier (BE)", "icmp.ident", FT_UINT16
, BASE_DEC_HEX
,
1976 "Identifier (big endian representation)", HFILL
}},
1979 {"Identifier (LE)", "icmp.ident_le", FT_UINT16
, BASE_DEC_HEX
,
1981 "Identifier (little endian representation)", HFILL
}},
1984 {"Sequence Number (BE)", "icmp.seq", FT_UINT16
,
1985 BASE_DEC_HEX
, NULL
, 0x0,
1986 "Sequence Number (big endian representation)", HFILL
}},
1988 {&hf_icmp_seq_num_le
,
1989 {"Sequence Number (LE)", "icmp.seq_le", FT_UINT16
,
1991 0x0, "Sequence Number (little endian representation)",
1995 {"MTU of next hop", "icmp.mtu", FT_UINT16
, BASE_DEC
, NULL
,
1999 {&hf_icmp_num_addrs
,
2000 {"Number of addresses", "icmp.num_addrs", FT_UINT8
, BASE_DEC
, NULL
,
2004 {&hf_icmp_addr_entry_size
,
2005 {"Address entry size", "icmp.addr_entry_size", FT_UINT8
, BASE_DEC
, NULL
,
2010 {"Lifetime", "icmp.lifetime", FT_UINT16
, BASE_DEC
, NULL
,
2015 {"Pointer", "icmp.pointer", FT_UINT32
, BASE_DEC
, NULL
,
2019 {&hf_icmp_router_address
,
2020 {"Router address", "icmp.router_address", FT_IPv4
, BASE_NONE
, NULL
,
2024 {&hf_icmp_pref_level
,
2025 {"Preference level", "icmp.pref_level", FT_INT32
, BASE_DEC
, NULL
,
2029 {&hf_icmp_originate_timestamp
,
2030 {"Originate Timestamp", "icmp.originate_timestamp", FT_UINT32
, BASE_DEC
, NULL
,
2034 {&hf_icmp_receive_timestamp
,
2035 {"Receive Timestamp", "icmp.receive_timestamp", FT_UINT32
, BASE_DEC
, NULL
,
2039 {&hf_icmp_transmit_timestamp
,
2040 {"Transmit Timestamp", "icmp.transmit_timestamp", FT_UINT32
, BASE_DEC
, NULL
,
2044 {&hf_icmp_address_mask
,
2045 {"Address Mask", "icmp.address_mask", FT_IPv4
, BASE_NONE
, NULL
,
2050 {"Gateway Address", "icmp.redir_gw", FT_IPv4
, BASE_NONE
,
2055 {"Extension Type", "icmp.mip.type", FT_UINT8
, BASE_DEC
,
2056 VALS(mip_extensions
), 0x0, NULL
, HFILL
}},
2058 {&hf_icmp_mip_length
,
2059 {"Length", "icmp.mip.length", FT_UINT8
, BASE_DEC
, NULL
,
2063 {&hf_icmp_mip_prefix_length
,
2064 {"Prefix Length", "icmp.mip.prefixlength", FT_UINT8
,
2065 BASE_DEC
, NULL
, 0x0,
2069 {"Sequence Number", "icmp.mip.seq", FT_UINT16
, BASE_DEC
,
2074 {"Registration Lifetime", "icmp.mip.life", FT_UINT16
,
2079 {&hf_icmp_mip_flags
,
2080 {"Flags", "icmp.mip.flags", FT_UINT16
, BASE_HEX
, NULL
,
2085 {"Registration Required", "icmp.mip.r", FT_BOOLEAN
, 16,
2087 "Registration with this FA is required", HFILL
}},
2090 {"Busy", "icmp.mip.b", FT_BOOLEAN
, 16, NULL
, 0x4000,
2091 "This FA will not accept requests at this time", HFILL
}},
2094 {"Home Agent", "icmp.mip.h", FT_BOOLEAN
, 16, NULL
, 0x2000,
2095 "Home Agent Services Offered", HFILL
}},
2098 {"Foreign Agent", "icmp.mip.f", FT_BOOLEAN
, 16, NULL
,
2100 "Foreign Agent Services Offered", HFILL
}},
2103 {"Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN
, 16,
2105 "Minimal encapsulation tunneled datagram support",
2109 {"GRE", "icmp.mip.g", FT_BOOLEAN
, 16, NULL
, 0x0400,
2110 "GRE encapsulated tunneled datagram support", HFILL
}},
2113 {"VJ Comp", "icmp.mip.v", FT_BOOLEAN
, 16, NULL
, 0x0200,
2114 "Van Jacobson Header Compression Support", HFILL
}},
2117 {"Reverse tunneling", "icmp.mip.rt", FT_BOOLEAN
, 16, NULL
,
2119 "Reverse tunneling support", HFILL
}},
2122 {"UDP tunneling", "icmp.mip.u", FT_BOOLEAN
, 16, NULL
,
2124 "UDP tunneling support", HFILL
}},
2127 {"Revocation support", "icmp.mip.x", FT_BOOLEAN
, 16, NULL
,
2129 "Registration revocation support", HFILL
}},
2131 {&hf_icmp_mip_reserved
,
2132 {"Reserved", "icmp.mip.reserved", FT_UINT16
, BASE_HEX
,
2137 {"Care-Of-Address", "icmp.mip.coa", FT_IPv4
, BASE_NONE
,
2141 {&hf_icmp_mip_challenge
,
2142 {"Challenge", "icmp.mip.challenge", FT_BYTES
, BASE_NONE
,
2146 {&hf_icmp_mip_content
,
2147 {"Content", "icmp.mip.content", FT_BYTES
, BASE_NONE
,
2152 {"ICMP Extensions", "icmp.ext", FT_NONE
, BASE_NONE
, NULL
,
2156 {&hf_icmp_ext_version
,
2157 {"Version", "icmp.ext.version", FT_UINT8
, BASE_DEC
, NULL
,
2161 {&hf_icmp_ext_reserved
,
2162 {"Reserved", "icmp.ext.res", FT_UINT16
, BASE_HEX
, NULL
,
2166 {&hf_icmp_ext_checksum
,
2167 {"Checksum", "icmp.ext.checksum", FT_UINT16
, BASE_HEX
,
2171 {&hf_icmp_ext_checksum_status
,
2172 {"Checksum Status", "icmp.ext.checksum.status", FT_UINT8
, BASE_NONE
,
2173 VALS(proto_checksum_vals
),
2177 {&hf_icmp_ext_length
,
2178 {"Length", "icmp.ext.length", FT_UINT16
, BASE_DEC
, NULL
,
2182 {&hf_icmp_ext_class
,
2183 {"Class", "icmp.ext.class", FT_UINT8
, BASE_DEC
,
2184 VALS(icmp_ext_class_str
), 0x0, NULL
, HFILL
}},
2186 {&hf_icmp_ext_c_type
,
2187 {"C-Type", "icmp.ext.ctype", FT_UINT8
, BASE_DEC
, NULL
,
2192 {"Data", "icmp.ext.data", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2195 {&hf_icmp_mpls_label
,
2196 {"Label", "icmp.mpls.label", FT_UINT24
, BASE_DEC
, NULL
,
2201 {"Experimental", "icmp.mpls.exp", FT_UINT24
, BASE_DEC
,
2206 {"Stack bit", "icmp.mpls.s", FT_BOOLEAN
, 8,
2207 TFS(&tfs_set_notset
), 0x01,
2211 {"Time to live", "icmp.mpls.ttl", FT_UINT8
, BASE_DEC
,
2215 {&hf_icmp_mpls_data
,
2216 {"Data", "icmp.mpls.data", FT_BYTES
, BASE_NONE
,
2221 {"Response frame", "icmp.resp_in", FT_FRAMENUM
, BASE_NONE
,
2222 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0,
2223 "The frame number of the corresponding response",
2227 {"No response seen", "icmp.no_resp", FT_NONE
, BASE_NONE
,
2229 "No corresponding response frame was seen",
2233 {"Request frame", "icmp.resp_to", FT_FRAMENUM
, BASE_NONE
,
2234 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0x0,
2235 "The frame number of the corresponding request", HFILL
}},
2238 {"Response time", "icmp.resptime", FT_DOUBLE
, BASE_NONE
,
2240 "The time between the request and the response, in ms.",
2243 {&hf_icmp_data_time
,
2244 {"Timestamp from icmp data", "icmp.data_time",
2246 ABSOLUTE_TIME_LOCAL
, NULL
, 0x0,
2247 "The timestamp in the first 8 or 16 bytes of the icmp data",
2250 {&hf_icmp_data_time_relative
,
2251 {"Timestamp from icmp data (relative)",
2252 "icmp.data_time_relative",
2253 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
2254 "The timestamp of the packet, relative to the timestamp in the first 8 or 16 bytes of the icmp data",
2258 {"Length", "icmp.length", FT_UINT8
,
2261 "The length of the original datagram", HFILL
}},
2262 {&hf_icmp_length_original_datagram
,
2263 {"Length of original datagram", "icmp.length.original_datagram", FT_UINT8
,
2266 "The length of the original datagram (length * 4)", HFILL
}},
2267 {&hf_icmp_int_info_role
,
2268 {"Interface Role", "icmp.int_info.role",
2269 FT_UINT8
, BASE_DEC
, VALS(interface_role_str
),
2270 INT_INFO_INTERFACE_ROLE
,
2272 {&hf_icmp_int_info_reserved
,
2273 {"Reserved", "icmp.int_info.reserved",
2274 FT_UINT8
, BASE_DEC
, NULL
, INT_INFO_RESERVED
,
2276 {&hf_icmp_int_info_ifindex
,
2277 {"ifIndex", "icmp.int_info.ifindex", FT_BOOLEAN
, 8, NULL
,
2279 "True: ifIndex of the interface included; False: ifIndex of the interface not included",
2281 {&hf_icmp_int_info_ipaddr
,
2282 {"IP Address", "icmp.int_info.ipaddr", FT_BOOLEAN
, 8,
2283 TFS(&tfs_present_not_present
),
2286 {&hf_icmp_int_info_name
,
2287 {"Interface Name", "icmp.int_info.name_present", FT_BOOLEAN
, 8,
2288 TFS(&tfs_present_not_present
),
2292 {&hf_icmp_int_info_mtu_present
,
2293 {"MTU", "icmp.int_info.mtu_present", FT_BOOLEAN
, 8, TFS(&tfs_present_not_present
),
2296 {&hf_icmp_int_info_index
,
2297 {"Interface Index", "icmp.int_info.index",
2298 FT_UINT32
, BASE_DEC
,
2301 {&hf_icmp_int_info_afi
,
2302 {"Address Family Identifier", "icmp.int_info.afi",
2303 FT_UINT16
, BASE_DEC
,
2305 "Address Family of the interface address", HFILL
}},
2306 {&hf_icmp_int_info_ipv4
,
2307 {"Source", "icmp.int_info.ipv4", FT_IPv4
, BASE_NONE
, NULL
,
2310 {&hf_icmp_int_info_ipv6
,
2311 {"Source", "icmp.int_info.ipv6", FT_IPv6
, BASE_NONE
, NULL
,
2314 {&hf_icmp_int_info_ipunknown
,
2315 {"Source", "icmp.int_info.ipunknown", FT_BYTES
, BASE_NONE
, NULL
,
2318 {&hf_icmp_int_info_name_length
,
2319 {"Name Length", "icmp.int_info.name_length", FT_UINT8
, BASE_DEC
, NULL
,
2322 {&hf_icmp_int_info_name_string
,
2323 {"Name", "icmp.int_info.name", FT_STRING
, BASE_NONE
, NULL
,
2326 {&hf_icmp_int_info_mtu
,
2327 {"Maximum Transmission Unit", "icmp.int_info.mtu",
2328 FT_UINT32
, BASE_DEC
,
2333 {&hf_icmp_ext_echo_seq_num
,
2334 {"Sequence Number", "icmp.ext.echo.seq", FT_UINT8
,
2335 BASE_DEC_HEX
, NULL
, 0x0,
2337 {&hf_icmp_ext_echo_req_reserved
,
2338 {"Reserved", "icmp.ext.echo.req.res", FT_UINT8
,
2339 BASE_HEX
, NULL
, 0xFE,
2341 {&hf_icmp_ext_echo_req_local
,
2342 {"Local bit", "icmp.ext.echo.req.local", FT_BOOLEAN
,
2343 8, TFS(&tfs_set_notset
), 0x01,
2345 {&hf_icmp_ext_echo_rsp_state
,
2346 {"State", "icmp.ext.echo.rsp.state", FT_UINT8
,
2347 BASE_DEC
, VALS(ext_echo_reply_state_str
), 0xE0,
2349 {&hf_icmp_ext_echo_rsp_reserved
,
2350 {"Reserved", "icmp.ext.echo.rsp.res", FT_UINT8
,
2351 BASE_HEX
, NULL
, 0x18,
2353 {&hf_icmp_ext_echo_rsp_active
,
2354 {"Active bit", "icmp.ext.echo.rsp.active", FT_BOOLEAN
,
2355 8, TFS(&tfs_set_notset
), 0x04,
2357 {&hf_icmp_ext_echo_rsp_ipv4
,
2358 {"IPv4 bit", "icmp.ext.echo.rsp.ipv4", FT_BOOLEAN
,
2359 8, TFS(&tfs_set_notset
), 0x02,
2361 {&hf_icmp_ext_echo_rsp_ipv6
,
2362 {"IPv6 bit", "icmp.ext.echo.rsp.ipv6", FT_BOOLEAN
,
2363 8, TFS(&tfs_set_notset
), 0x01,
2365 {&hf_icmp_int_ident_name_string
,
2366 {"Name", "icmp.int_ident.name", FT_STRING
,
2367 BASE_NONE
, NULL
, 0x0,
2369 {&hf_icmp_int_ident_index
,
2370 {"Interface Index", "icmp.int_ident.index", FT_UINT32
,
2371 BASE_DEC
, NULL
, 0x0,
2373 {&hf_icmp_int_ident_afi
,
2374 {"Address Family Identifier", "icmp.int_ident.afi", FT_UINT16
,
2375 BASE_DEC
, VALS(afn_vals
), 0x0,
2376 "Address Family of the interface address", HFILL
}},
2377 {&hf_icmp_int_ident_addr_length
,
2378 {"Address Length", "icmp.int_ident.addr_length", FT_UINT8
,
2379 BASE_DEC
, NULL
, 0x0,
2381 {&hf_icmp_int_ident_reserved
,
2382 {"Reserved", "icmp.int_ident.reserved", FT_BYTES
,
2383 BASE_NONE
, NULL
, 0x0,
2385 {&hf_icmp_int_ident_ipv4
,
2386 {"Address", "icmp.int_ident.ipv4", FT_IPv4
,
2387 BASE_NONE
, NULL
, 0x0,
2389 {&hf_icmp_int_ident_ipv6
,
2390 {"Address", "icmp.int_ident.ipv6", FT_IPv6
,
2391 BASE_NONE
, NULL
, 0x0,
2393 {&hf_icmp_int_ident_address
,
2394 {"Address", "icmp.int_ident.address", FT_BYTES
,
2395 BASE_NONE
, NULL
, 0x0,
2400 static int *ett
[] = {
2403 &ett_icmp_mip_flags
,
2404 /* MPLS extensions */
2406 &ett_icmp_ext_object
,
2407 &ett_icmp_mpls_stack_object
,
2408 /* Interface Information Object RFC 5837 */
2409 &ett_icmp_interface_info_object
,
2410 &ett_icmp_interface_ipaddr
,
2411 &ett_icmp_interface_name
2414 static ei_register_info ei
[] = {
2415 { &ei_icmp_type_deprecated
, { "icmp.type.deprecated", PI_DEPRECATED
, PI_NOTE
, "Type is deprecated", EXPFILL
}},
2416 { &ei_icmp_resp_not_found
, { "icmp.resp_not_found", PI_SEQUENCE
, PI_WARN
, "Response not found", EXPFILL
}},
2417 { &ei_icmp_checksum
, { "icmp.checksum_bad", PI_CHECKSUM
, PI_WARN
, "Bad checksum", EXPFILL
}},
2418 { &ei_icmp_ext_checksum
, { "icmp.ext.checksum_bad", PI_CHECKSUM
, PI_WARN
, "Bad checksum", EXPFILL
}},
2421 module_t
*icmp_module
;
2422 expert_module_t
* expert_icmp
;
2425 proto_register_protocol("Internet Control Message Protocol",
2427 proto_register_field_array(proto_icmp
, hf
, array_length(hf
));
2428 expert_icmp
= expert_register_protocol(proto_icmp
);
2429 expert_register_field_array(expert_icmp
, ei
, array_length(ei
));
2430 proto_register_subtree_array(ett
, array_length(ett
));
2432 icmp_module
= prefs_register_protocol(proto_icmp
, NULL
);
2434 prefs_register_bool_preference(icmp_module
, "favor_icmp_mpls",
2435 "Favor ICMP extensions for MPLS",
2436 "Whether the 128th and following bytes of the ICMP payload should be decoded as MPLS extensions or as a portion of the original packet",
2437 &favor_icmp_mpls_ext
);
2439 register_seq_analysis("icmp", "ICMP Flows", proto_icmp
, NULL
, TL_REQUIRES_COLUMNS
, icmp_seq_analysis_packet
);
2440 icmp_handle
= register_dissector("icmp", dissect_icmp
, proto_icmp
);
2441 icmp_heur_subdissector_list
= register_heur_dissector_list_with_description("icmp", "ICMP Echo payload", proto_icmp
);
2442 register_dissector("icmp_extension", dissect_icmp_extension
, proto_icmp
);
2443 icmp_tap
= register_tap("icmp");
2446 void proto_reg_handoff_icmp(void)
2448 capture_dissector_handle_t icmp_cap_handle
;
2451 * Get handle for the IP dissector.
2453 ip_handle
= find_dissector_add_dependency("ip", proto_icmp
);
2455 dissector_add_uint("ip.proto", IP_PROTO_ICMP
, icmp_handle
);
2456 icmp_cap_handle
= create_capture_dissector_handle(capture_icmp
, proto_icmp
);
2457 capture_dissector_add_uint("ip.proto", IP_PROTO_ICMP
, icmp_cap_handle
);
2461 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2466 * indent-tabs-mode: t
2469 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2470 * :indentSize=8:tabSize=8:noTabs=false: