Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-icmp.c
blob74fbe2d92bd8eeabbab7ee27046eba9015c0fe2f
1 /* packet-icmp.c
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>
21 #include "config.h"
23 #include <stdlib.h>
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 #include <epan/tfs.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;
48 static int icmp_tap;
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;
61 } icmp_conv_info_t;
63 static icmp_transaction_t *transaction_start(packet_info * pinfo,
64 proto_tree * tree,
65 uint32_t * key);
66 static icmp_transaction_t *transaction_end(packet_info * pinfo,
67 proto_tree * tree,
68 uint32_t * key);
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;
101 /* Mobile ip */
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;
159 static int ett_icmp;
160 static int ett_icmp_mip;
161 static int ett_icmp_mip_flags;
163 /* extensions */
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
202 #define ICMP_ECHO 8
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
209 #define ICMP_IREQ 15
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"},
247 {1, "Reserved"},
248 {2, "Reserved"},
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"},
279 {0, NULL}
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"},
299 {0, NULL}
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"},
307 {0, NULL}
310 static const value_string alt_host_code_str[] = {
311 {0, "Alternate address for host"},
312 {0, NULL}
315 static const value_string rtradvert_code_str[] = {
316 { 0, "Normal router advertisement"},
317 {16, "Does not route common traffic"},
318 {0, NULL}
321 static const value_string ttl_code_str[] = {
322 {0, "Time to live exceeded in transit"},
323 {1, "Fragment reassembly time exceeded"},
324 {0, NULL}
327 static const value_string par_code_str[] = {
328 {0, "Pointer indicates the error"},
329 {1, "Required option missing"},
330 {2, "Bad length"},
331 {0, NULL}
334 static const value_string photuris_code_str[] = {
335 {0, "Bad SPI"},
336 {1, "Authentication Failed"},
337 {2, "Decompression Failed"},
338 {3, "Decryption Failed"},
339 {4, "Need Authentication"},
340 {5, "Need Authorization"},
341 {0, NULL}
344 static const value_string ext_echo_req_code_str[] = {
345 {0, "No error"},
346 {0, NULL}
349 static const value_string ext_echo_reply_code_str[] = {
350 {0, "No error"},
351 {1, "Malformed Query"},
352 {2, "No Such Interface"},
353 {3, "No Such Table Entry"},
354 {4, "Multiple Interfaces Satisfy Query"},
355 {0, NULL}
358 static const value_string ext_echo_reply_state_str[] = {
359 {0, "Reserved"},
360 {1, "Incomplete"},
361 {2, "Reachable"},
362 {3, "Stale"},
363 {4, "Delay"},
364 {5, "Probe"},
365 {6, "Failed"},
366 {0, NULL}
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"},
377 {0, NULL}
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"},
383 /* RFC 2002 */
384 {ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
385 {ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
386 {0, NULL}
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"},
393 {0, NULL}
396 /* RFC 5837 ICMP extension - Interface Information Object
397 * Interface Role
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"},
404 {0, NULL}
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);
452 if (!sai)
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) {
468 sai->port_src = 0;
469 sai->port_dst = p_icmp_info->type * 256 + p_icmp_info->code;
473 sai->line_style = 1;
474 sai->conv_num = 0;
475 sai->display = true;
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? */
487 conv =
488 find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype),
489 0, 0, 0);
490 if (conv == NULL) {
491 /* No, this is a new conversation. */
492 conv =
493 conversation_new(pinfo->num, &pinfo->src,
494 &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype), 0, 0, 0);
496 return conv;
500 * Dissect the mobile ip advertisement extensions.
502 static void
503 dissect_mip_extensions(tvbuff_t * tvb, int offset, proto_tree * tree)
505 uint8_t type;
506 uint8_t length;
507 proto_item *ti;
508 proto_tree *mip_tree = NULL;
509 int numCOAs;
510 int i;
511 static int * const flags[] = {
512 &hf_icmp_mip_r,
513 &hf_icmp_mip_b,
514 &hf_icmp_mip_h,
515 &hf_icmp_mip_f,
516 &hf_icmp_mip_m,
517 &hf_icmp_mip_g,
518 &hf_icmp_mip_v,
519 &hf_icmp_mip_rt,
520 &hf_icmp_mip_u,
521 &hf_icmp_mip_x,
522 &hf_icmp_mip_reserved,
523 NULL
526 /* Not much to do if we're not parsing everything */
527 if (!tree)
528 return;
530 while (tvb_reported_length_remaining(tvb, offset) > 0) {
531 type = tvb_get_uint8(tvb, offset + 0);
532 if (type) {
533 length = tvb_get_uint8(tvb, offset + 1);
534 } else {
535 length = 0;
538 mip_tree = proto_tree_add_subtree_format(tree, tvb, offset,
539 1, ett_icmp_mip, &ti,
540 "Ext: %s", val_to_str(type,
541 mip_extensions,
542 "Unknown ext %u"));
543 proto_tree_add_item(mip_tree, hf_icmp_mip_type,
544 tvb, offset, 1,
545 ENC_BIG_ENDIAN);
546 offset++;
547 if (type != ICMP_MIP_EXTENSION_PAD)
549 proto_item_set_len(ti, length + 2);
551 /* length */
552 proto_tree_add_item(mip_tree, hf_icmp_mip_length,
553 tvb, offset, 1,
554 ENC_BIG_ENDIAN);
555 offset++;
558 switch (type) {
559 case ICMP_MIP_EXTENSION_PAD:
560 /* One byte padding extension */
561 break;
562 case ICMP_MIP_MOB_AGENT_ADV:
563 /* Mobility Agent Advertisement Extension (RFC 2002) */
564 /* Add our fields */
565 /* sequence number */
566 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb,
567 offset, 2, ENC_BIG_ENDIAN);
568 offset += 2;
569 /* Registration Lifetime */
570 proto_tree_add_item(mip_tree, hf_icmp_mip_life,
571 tvb, offset, 2,
572 ENC_BIG_ENDIAN);
573 offset += 2;
574 /* flags */
575 proto_tree_add_bitmask(mip_tree, tvb, offset, hf_icmp_mip_flags, ett_icmp_mip_flags, flags, ENC_BIG_ENDIAN);
576 offset += 2;
578 /* COAs */
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,
583 offset, 4,
584 ENC_BIG_ENDIAN);
585 offset += 4;
587 break;
588 case ICMP_MIP_PREFIX_LENGTHS:
589 /* Prefix-Lengths Extension (RFC 2002) */
590 /* Add our fields */
592 /* prefix lengths */
593 for (i = 0; i < length; i++) {
594 proto_tree_add_item(mip_tree,
595 hf_icmp_mip_prefix_length,
596 tvb, offset, 1,
597 ENC_BIG_ENDIAN);
598 offset++;
600 break;
601 case ICMP_MIP_CHALLENGE:
602 /* Challenge Extension (RFC 3012) */
603 /* challenge */
604 proto_tree_add_item(mip_tree,
605 hf_icmp_mip_challenge, tvb,
606 offset, length, ENC_NA);
607 offset += length;
609 break;
610 default:
611 /* data, if any */
612 if (length != 0) {
613 proto_tree_add_item(mip_tree, hf_icmp_mip_content, tvb, offset, length - 4, ENC_NA);
614 offset += length;
617 break;
621 } /* dissect_mip_extensions */
623 static bool
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;
630 bool unknown_object;
631 uint8_t c_type;
632 unknown_object = false;
633 /* Object length */
634 obj_length = tvb_get_ntohs(tvb, offset);
636 obj_trunc_length =
637 MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
639 /* C-Type */
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 */
645 offset += 4;
647 switch (c_type) {
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);
656 break;
657 default:
658 unknown_object = true;
659 } /* end switch c_type */
660 return unknown_object;
663 static bool
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;
672 int obj_end_offset;
673 unsigned label;
674 uint8_t ttl;
675 uint8_t tmp;
676 bool unknown_object;
677 uint8_t c_type;
678 unknown_object = false;
679 /* Object length */
680 obj_length = tvb_get_ntohs(tvb, offset);
682 obj_trunc_length =
683 MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
684 obj_end_offset = offset + obj_trunc_length;
685 /* C-Type */
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 */
691 offset += 4;
693 switch (c_type) {
694 case MPLS_STACK_ENTRY_C_TYPE:
695 proto_item_set_text(tf_object, "MPLS Stack Entry");
696 /* For each entry */
697 while (offset + 4 <= obj_end_offset) {
698 if (tvb_reported_length_remaining(tvb, offset) < 4) {
699 /* Not enough room in the packet ! */
700 break;
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,
704 tvb, offset, 4,
705 ett_icmp_mpls_stack_object, &tf_entry, " ");
707 /* Label */
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,
721 offset + 2, 1, tmp);
723 proto_item_append_text(tf_entry, ", Exp: %u",
724 (tmp >> 1) & 0x07);
726 /* Stack bit */
727 proto_tree_add_boolean(mpls_stack_object_tree,
728 hf_icmp_mpls_s, tvb,
729 offset + 2, 1, tmp);
731 proto_item_append_text(tf_entry, ", S: %u",
732 tmp & 0x01);
734 /* TTL */
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);
743 /* Skip the entry */
744 offset += 4;
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);
750 break;
752 default:
754 unknown_object = true;
756 break;
757 } /* end switch c_type */
758 return unknown_object;
760 } /* end dissect_mpls_stack_entry_object */
762 /* Dissect Interface Information Object RFC 5837*/
763 static bool
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;
771 int obj_end_offset;
772 uint8_t c_type;
773 bool unknown_object;
774 uint8_t if_index_flag;
775 uint8_t ipaddr_flag;
776 uint8_t name_flag;
777 uint8_t mtu_flag;
778 uint16_t afi;
779 uint8_t int_name_length = 0;
781 unknown_object = false;
782 /* Object length */
783 obj_length = tvb_get_ntohs(tvb, offset);
785 obj_trunc_length =
786 MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
787 obj_end_offset = offset + obj_trunc_length;
789 /* C-Type */
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 */
795 return 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,
811 NULL
813 proto_tree_add_bitmask(ext_object_tree, tvb, offset + 3,
814 hf_icmp_ext_c_type,
815 ett_icmp_interface_info_object,
816 c_type_fields, ENC_BIG_ENDIAN);
819 /* skip header */
820 offset += 4;
822 /*if ifIndex is set, next 32 bits are ifIndex */
823 if (if_index_flag) {
824 proto_tree_add_item(ext_object_tree, hf_icmp_int_info_index, tvb, offset, 4, ENC_NA);
825 offset += 4;
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,
843 afi);
844 offset += 2;
846 proto_tree_add_item(int_ipaddr_object_tree, hf_icmp_reserved, tvb, offset, 2, ENC_NA);
847 offset += 2;
849 switch(afi){
850 case 1: /* IPv4 */
851 proto_tree_add_item(int_ipaddr_object_tree, hf_icmp_int_info_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
852 offset += 4;
853 break;
854 case 2: /* IPv6 */
855 proto_tree_add_item(int_ipaddr_object_tree, hf_icmp_int_info_ipv6, tvb, offset, 16, ENC_NA);
856 offset += 16;
857 break;
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);
860 return false;
865 /* Interface Name Sub Object */
866 if (name_flag) {
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);
874 offset += 1;
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;
881 /* MTU Sub Object */
882 if (mtu_flag) {
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*/
892 static bool
893 dissect_interface_identification_object(tvbuff_t * tvb, int offset,
894 proto_tree * ext_object_tree,
895 proto_item * tf_object)
897 proto_item *ti;
898 uint16_t obj_length;
899 uint8_t c_type;
900 bool unknown_object;
901 uint32_t afi;
902 uint32_t addr_length;
904 unknown_object = false;
905 /* Object length */
906 obj_length = tvb_get_ntohs(tvb, offset);
908 /* C-Type */
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 */
914 return 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"));
919 offset += 4;
921 switch(c_type) {
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);
924 break;
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);
927 break;
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);
930 offset += 2;
931 proto_tree_add_item_ret_uint(ext_object_tree, hf_icmp_int_ident_addr_length, tvb, offset, 1, ENC_BIG_ENDIAN, &addr_length);
932 offset += 1;
933 proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_reserved, tvb, offset, 1, ENC_NA);
934 offset += 1;
935 switch(afi){
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);
939 offset += 4;
940 addr_length -= 4;
942 break;
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);
946 offset += 16;
947 addr_length -= 16;
949 break;
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 */
959 static int
960 dissect_icmp_extension(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_)
962 int offset = 0;
963 uint8_t version;
964 uint8_t class_num;
965 uint8_t c_type;
966 uint16_t obj_length, obj_trunc_length, checksum;
967 proto_item *ti, *tf_object;
968 proto_tree *ext_tree, *ext_object_tree;
969 int obj_end_offset;
970 unsigned reported_length;
971 bool unknown_object;
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 */ ) {
984 return offset;
987 ext_tree = proto_item_add_subtree(ti, ett_icmp_ext);
989 /* Version */
990 version = hi_nibble(tvb_get_uint8(tvb, offset));
991 proto_tree_add_uint(ext_tree, hf_icmp_ext_version, tvb, offset, 1,
992 version);
994 /* Reserved */
995 proto_tree_add_item(ext_tree, hf_icmp_ext_reserved,
996 tvb, offset, 2, ENC_BIG_ENDIAN);
998 /* Checksum */
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);
1004 } else {
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)");
1012 return offset;
1015 /* Skip the common header */
1016 offset += 4;
1018 /* While there is enough room to read an object */
1019 while (tvb_reported_length_remaining(tvb, offset) >=
1020 4 /* Object header */ ) {
1021 /* Object length */
1022 obj_length = tvb_get_ntohs(tvb, offset);
1024 obj_trunc_length =
1025 MIN(obj_length,
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);
1038 /* Class */
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);
1043 /* C-Type */
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");
1050 break;
1054 switch (class_num) {
1055 case MPLS_STACK_ENTRY_OBJECT_CLASS:
1056 unknown_object =
1057 dissect_mpls_stack_entry_object(tvb, offset,
1058 ext_object_tree,
1059 tf_object);
1060 break;
1061 case INTERFACE_INFORMATION_OBJECT_CLASS:
1062 unknown_object =
1063 dissect_interface_information_object(tvb,
1064 offset,
1065 ext_object_tree,
1066 tf_object);
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");
1072 break;
1073 case MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS:
1074 unknown_object =
1075 dissect_mpls_extended_payload_object(tvb,
1076 offset,
1077 ext_object_tree,
1078 tf_object);
1079 break;
1080 case INTERFACE_IDENTIFICATION_OBJECT_CLASS:
1081 unknown_object =
1082 dissect_interface_identification_object(tvb,
1083 offset,
1084 ext_object_tree,
1085 tf_object);
1086 break;
1087 default:
1089 unknown_object = true;
1091 break;
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 */
1099 offset += 4;
1101 proto_item_set_text(tf_object,
1102 "Unknown object (%d/%d)",
1103 class_num, c_type);
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);
1110 /* */
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;
1119 return offset;
1122 /* ======================================================================= */
1124 Note: We are tracking conversations via these keys:
1126 0 1 2 3
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1129 | |G| Checksum |
1130 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1131 | Identifier | Sequence Number |
1132 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1133 | VLAN ID |
1134 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1136 static icmp_transaction_t *transaction_start(packet_info * pinfo,
1137 proto_tree * tree,
1138 uint32_t * key)
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];
1144 proto_item *it;
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,
1154 icmp_info);
1157 if (!PINFO_FD_VISITED(pinfo)) {
1158 /* this is a new request, create a new transaction structure and map it to the
1159 unmatched table
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);
1173 } else {
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;
1184 icmp_trans =
1185 (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->matched_pdus,
1186 icmp_key);
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,
1195 ENC_NA);
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");
1206 return NULL;
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);
1219 return icmp_trans;
1221 } /* transaction_start() */
1223 /* ======================================================================= */
1224 static icmp_transaction_t *transaction_end(packet_info * pinfo,
1225 proto_tree * tree,
1226 uint32_t * key)
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];
1232 proto_item *it;
1233 nstime_t ns;
1234 double resp_time;
1236 conversation =
1237 find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
1238 conversation_pt_to_conversation_type(pinfo->ptype), 0, 0, 0);
1239 if (conversation == NULL) {
1240 return NULL;
1243 icmp_info = (icmp_conv_info_t *)conversation_get_proto_data(conversation, proto_icmp);
1244 if (icmp_info == NULL) {
1245 return NULL;
1248 if (!PINFO_FD_VISITED(pinfo)) {
1249 uint32_t frame_num;
1251 icmp_key[0].length = 3;
1252 icmp_key[0].key = key;
1253 icmp_key[1].length = 0;
1254 icmp_key[1].key = NULL;
1255 icmp_trans =
1256 (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->unmatched_pdus,
1257 icmp_key);
1258 if (icmp_trans == NULL) {
1259 return NULL;
1262 /* we have already seen this response, or an identical one */
1263 if (icmp_trans->resp_frame != 0) {
1264 return NULL;
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);
1285 } else {
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;
1296 icmp_trans =
1297 (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->matched_pdus,
1298 icmp_key);
1300 if (icmp_trans == NULL) {
1301 return 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);
1321 return icmp_trans;
1323 } /* transaction_end() */
1325 static bool
1326 update_best_guess_timestamp(time_t secs, int64_t usecs, const nstime_t *comp_ts, nstime_t *out_ts, nstime_t *best_diff)
1328 nstime_t ts, delta;
1329 if (usecs < 1000000 && usecs >= 0) {
1330 /* suseconds_t allows -1 but we'll reject it */
1331 ts.secs = secs;
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);
1337 return true;
1340 return false;
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
1359 * time.)
1362 if (!tvb_bytes_exist(tvb, offset, 8)) {
1363 return 0;
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;
1372 int len = 0;
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)) {
1379 len = 16;
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)) {
1393 len = 8;
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)) {
1401 len = 8;
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)) {
1409 len = 16;
1413 return len;
1416 #define MSPERDAY 86400000
1418 /* ======================================================================= */
1419 static uint32_t
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) {
1436 return be_ts;
1439 if (le_ts < MSPERDAY && be_ts >= MSPERDAY) {
1440 return le_ts;
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))
1456 return saved_be_ts;
1457 return saved_le_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)) {
1465 return be_ts;
1467 return le_ts;
1468 } /* get_best_guess_mstimeofday() */
1470 static bool
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);
1474 return true;
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.
1483 static int
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;
1488 uint8_t icmp_type;
1489 uint8_t icmp_code;
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;
1495 uint32_t i;
1496 bool save_in_error_pkt;
1497 tvbuff_t *next_tvb;
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);
1513 type_str =
1514 val_to_str_const(icmp_type, icmp_type_str,
1515 "Unknown ICMP (obsolete or malformed?)");
1517 switch (icmp_type) {
1518 case ICMP_UNREACH:
1519 code_str =
1520 val_to_str(icmp_code, unreach_code_str,
1521 "Unknown code: %u");
1522 break;
1523 case ICMP_REDIRECT:
1524 code_str =
1525 val_to_str(icmp_code, redir_code_str,
1526 "Unknown code: %u");
1527 break;
1528 case ICMP_ALTHOST:
1529 code_str =
1530 val_to_str(icmp_code, alt_host_code_str,
1531 "Unknown code: %u");
1532 icmp_original_dgram_length = 0;
1533 break;
1534 case ICMP_RTRADVERT:
1535 switch (icmp_code) {
1536 case 0: /* Mobile-Ip */
1537 case 16: /* Mobile-Ip */
1538 type_str = "Mobile IP Advertisement";
1539 break;
1540 } /* switch icmp_code */
1541 code_str =
1542 val_to_str(icmp_code, rtradvert_code_str,
1543 "Unknown code: %u");
1544 break;
1545 case ICMP_TIMXCEED:
1546 code_str =
1547 val_to_str(icmp_code, ttl_code_str,
1548 "Unknown code: %u");
1549 break;
1550 case ICMP_PARAMPROB:
1551 code_str =
1552 val_to_str(icmp_code, par_code_str,
1553 "Unknown code: %u");
1554 break;
1555 case ICMP_PHOTURIS:
1556 code_str =
1557 val_to_str(icmp_code, photuris_code_str,
1558 "Unknown code: %u");
1559 break;
1560 case ICMP_EXTECHO:
1561 code_str =
1562 val_to_str(icmp_code, ext_echo_req_code_str,
1563 "Unknown code: %u");
1564 break;
1565 case ICMP_EXTECHOREPLY:
1566 code_str =
1567 val_to_str(icmp_code, ext_echo_reply_code_str,
1568 "Unknown code: %u");
1569 break;
1570 default:
1571 code_str = NULL;
1572 break;
1575 col_add_fstr(pinfo->cinfo, COL_INFO, "%-20s", type_str);
1576 if (code_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,
1587 ENC_BIG_ENDIAN);
1588 proto_item_append_text(ti, " (%s)", type_str);
1589 switch (icmp_type) {
1590 case ICMP_SOURCEQUENCH:
1591 case ICMP_ALTHOST:
1592 case ICMP_IREQ:
1593 case ICMP_IREQREPLY:
1594 case ICMP_MASKREQ:
1595 case ICMP_MASKREPLY:
1596 case 30:
1597 case 31:
1598 case 32:
1599 case 33:
1600 case 34:
1601 case 35:
1602 case 36:
1603 case 37:
1604 case 38:
1605 case 39:
1606 expert_add_info(pinfo, ti, &ei_icmp_type_deprecated);
1607 break;
1608 default:
1609 break;
1612 ti = proto_tree_add_item(icmp_tree, hf_icmp_code, tvb, 1, 1,
1613 ENC_BIG_ENDIAN);
1614 if (code_str) {
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
1622 it. */
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);
1625 } else {
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:
1635 case ICMP_ECHO:
1636 case ICMP_TSTAMP:
1637 case ICMP_TSTAMPREPLY:
1638 case ICMP_IREQ:
1639 case ICMP_IREQREPLY:
1640 case ICMP_MASKREQ:
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));
1648 if (iph != NULL) {
1649 col_append_fstr(pinfo->cinfo, COL_INFO, ", ttl=%u", iph->ip_ttl);
1651 break;
1653 case ICMP_UNREACH:
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);
1662 } else {
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);
1668 } else {
1669 proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 4, 4, ENC_NA);
1671 break;
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)));
1678 break;
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);
1688 } else {
1689 proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 5, 3, ENC_NA);
1691 break;
1693 case ICMP_REDIRECT:
1694 proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4, ENC_BIG_ENDIAN);
1695 break;
1697 case ICMP_TIMXCEED:
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);
1705 } else {
1706 proto_tree_add_item(icmp_tree, hf_icmp_unused, tvb, 4, 4, ENC_NA);
1708 break;
1710 case ICMP_EXTECHO:
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);
1716 break;
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);
1727 break;
1731 /* Decode the additional information in the packet. */
1732 switch (icmp_type) {
1733 case ICMP_UNREACH:
1734 case ICMP_TIMXCEED:
1735 case ICMP_PARAMPROB:
1736 case ICMP_SOURCEQUENCH:
1737 case ICMP_REDIRECT:
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
1741 "real" packets. */
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);
1765 } else {
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) &&
1775 favor_icmp_mpls_ext
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);
1796 break;
1797 case ICMP_ECHOREPLY:
1798 case ICMP_ECHO:
1799 if (icmp_type == ICMP_ECHOREPLY) {
1800 if (!pinfo->flags.in_error_pkt) {
1801 conv_key[0] =
1802 (uint32_t) tvb_get_ntohs(tvb, 2);
1803 if (conv_key[0] == 0xffff) {
1804 conv_key[0] = 0;
1806 if (pinfo->flags.in_gre_pkt && prefs.strict_conversation_tracking_heuristics)
1807 conv_key[0] |= 0x00010000; /* set a bit for "in GRE" */
1808 conv_key[1] =
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;
1812 trans =
1813 transaction_end(pinfo, icmp_tree,
1814 conv_key);
1816 } else {
1817 if (!pinfo->flags.in_error_pkt) {
1818 uint16_t tmp[2];
1820 tmp[0] = ~tvb_get_ntohs(tvb, 2);
1821 tmp[1] = ~0x0800; /* The difference between echo request & reply */
1822 conv_key[0] =
1823 ip_checksum((uint8_t *) & tmp,
1824 sizeof(tmp));
1825 if (pinfo->flags.in_gre_pkt && prefs.strict_conversation_tracking_heuristics) {
1826 conv_key[0] |= 0x00010000; /* set a bit for "in GRE" */
1828 conv_key[1] =
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;
1832 trans =
1833 transaction_start(pinfo, icmp_tree,
1834 conv_key);
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);
1846 break;
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);
1854 if (len) {
1855 proto_tree_add_time(icmp_tree, hf_icmp_data_time,
1856 tvb, 8, len, &ts);
1857 nstime_delta(&time_relative, &pinfo->abs_ts,
1858 &ts);
1859 ti = proto_tree_add_time(icmp_tree,
1860 hf_icmp_data_time_relative,
1861 tvb, 8, len,
1862 &time_relative);
1863 proto_item_set_generated(ti);
1864 call_data_dissector(tvb_new_subset_remaining(tvb,
1865 8 + len),
1866 pinfo, icmp_tree);
1867 } else {
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);
1874 break;
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)) {
1883 /* Mobile-Ip */
1884 dissect_mip_extensions(tvb, 8 + i * 8,
1885 icmp_tree);
1887 } else {
1888 call_data_dissector(tvb_new_subset_remaining(tvb, 8),
1889 pinfo, icmp_tree);
1891 break;
1893 case ICMP_TSTAMP:
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)) %
1900 86400000);
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)));
1913 break;
1915 case ICMP_MASKREQ:
1916 case ICMP_MASKREPLY:
1917 proto_tree_add_item(icmp_tree, hf_icmp_address_mask, tvb, 8, 4, ENC_BIG_ENDIAN);
1918 break;
1920 case ICMP_EXTECHO:
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);
1925 break;
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);
1935 if (trans) {
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[] = {
1945 {&hf_icmp_type,
1946 {"Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1947 NULL, HFILL}},
1949 {&hf_icmp_code,
1950 {"Code", "icmp.code", FT_UINT8, BASE_DEC, NULL, 0x0,
1951 NULL, HFILL}},
1953 {&hf_icmp_checksum,
1954 {"Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL,
1955 0x0,
1956 NULL, HFILL}},
1958 {&hf_icmp_checksum_status,
1959 {"Checksum Status", "icmp.checksum.status", FT_UINT8, BASE_NONE,
1960 VALS(proto_checksum_vals), 0x0,
1961 NULL, HFILL}},
1963 {&hf_icmp_unused,
1964 {"Unused", "icmp.unused", FT_BYTES,
1965 BASE_NONE, NULL, 0x0,
1966 NULL, HFILL}},
1968 {&hf_icmp_reserved,
1969 {"Reserved", "icmp.reserved", FT_BYTES,
1970 BASE_NONE, NULL, 0x0,
1971 NULL, HFILL}},
1973 {&hf_icmp_ident,
1974 {"Identifier (BE)", "icmp.ident", FT_UINT16, BASE_DEC_HEX,
1975 NULL, 0x0,
1976 "Identifier (big endian representation)", HFILL}},
1978 {&hf_icmp_ident_le,
1979 {"Identifier (LE)", "icmp.ident_le", FT_UINT16, BASE_DEC_HEX,
1980 NULL, 0x0,
1981 "Identifier (little endian representation)", HFILL}},
1983 {&hf_icmp_seq_num,
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,
1990 BASE_DEC_HEX, NULL,
1991 0x0, "Sequence Number (little endian representation)",
1992 HFILL}},
1994 {&hf_icmp_mtu,
1995 {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL,
1996 0x0,
1997 NULL, HFILL}},
1999 {&hf_icmp_num_addrs,
2000 {"Number of addresses", "icmp.num_addrs", FT_UINT8, BASE_DEC, NULL,
2001 0x0,
2002 NULL, HFILL}},
2004 {&hf_icmp_addr_entry_size,
2005 {"Address entry size", "icmp.addr_entry_size", FT_UINT8, BASE_DEC, NULL,
2006 0x0,
2007 NULL, HFILL}},
2009 {&hf_icmp_lifetime,
2010 {"Lifetime", "icmp.lifetime", FT_UINT16, BASE_DEC, NULL,
2011 0x0,
2012 NULL, HFILL}},
2014 {&hf_icmp_pointer,
2015 {"Pointer", "icmp.pointer", FT_UINT32, BASE_DEC, NULL,
2016 0x0,
2017 NULL, HFILL}},
2019 {&hf_icmp_router_address,
2020 {"Router address", "icmp.router_address", FT_IPv4, BASE_NONE, NULL,
2021 0x0,
2022 NULL, HFILL}},
2024 {&hf_icmp_pref_level,
2025 {"Preference level", "icmp.pref_level", FT_INT32, BASE_DEC, NULL,
2026 0x0,
2027 NULL, HFILL}},
2029 {&hf_icmp_originate_timestamp,
2030 {"Originate Timestamp", "icmp.originate_timestamp", FT_UINT32, BASE_DEC, NULL,
2031 0x0,
2032 NULL, HFILL}},
2034 {&hf_icmp_receive_timestamp,
2035 {"Receive Timestamp", "icmp.receive_timestamp", FT_UINT32, BASE_DEC, NULL,
2036 0x0,
2037 NULL, HFILL}},
2039 {&hf_icmp_transmit_timestamp,
2040 {"Transmit Timestamp", "icmp.transmit_timestamp", FT_UINT32, BASE_DEC, NULL,
2041 0x0,
2042 NULL, HFILL}},
2044 {&hf_icmp_address_mask,
2045 {"Address Mask", "icmp.address_mask", FT_IPv4, BASE_NONE, NULL,
2046 0x0,
2047 NULL, HFILL}},
2049 {&hf_icmp_redir_gw,
2050 {"Gateway Address", "icmp.redir_gw", FT_IPv4, BASE_NONE,
2051 NULL, 0x0,
2052 NULL, HFILL}},
2054 {&hf_icmp_mip_type,
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,
2060 0x0,
2061 NULL, HFILL}},
2063 {&hf_icmp_mip_prefix_length,
2064 {"Prefix Length", "icmp.mip.prefixlength", FT_UINT8,
2065 BASE_DEC, NULL, 0x0,
2066 NULL, HFILL}},
2068 {&hf_icmp_mip_seq,
2069 {"Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC,
2070 NULL, 0x0,
2071 NULL, HFILL}},
2073 {&hf_icmp_mip_life,
2074 {"Registration Lifetime", "icmp.mip.life", FT_UINT16,
2075 BASE_DEC, NULL,
2076 0x0,
2077 NULL, HFILL}},
2079 {&hf_icmp_mip_flags,
2080 {"Flags", "icmp.mip.flags", FT_UINT16, BASE_HEX, NULL,
2081 0x0,
2082 NULL, HFILL}},
2084 {&hf_icmp_mip_r,
2085 {"Registration Required", "icmp.mip.r", FT_BOOLEAN, 16,
2086 NULL, 0x8000,
2087 "Registration with this FA is required", HFILL}},
2089 {&hf_icmp_mip_b,
2090 {"Busy", "icmp.mip.b", FT_BOOLEAN, 16, NULL, 0x4000,
2091 "This FA will not accept requests at this time", HFILL}},
2093 {&hf_icmp_mip_h,
2094 {"Home Agent", "icmp.mip.h", FT_BOOLEAN, 16, NULL, 0x2000,
2095 "Home Agent Services Offered", HFILL}},
2097 {&hf_icmp_mip_f,
2098 {"Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 16, NULL,
2099 0x1000,
2100 "Foreign Agent Services Offered", HFILL}},
2102 {&hf_icmp_mip_m,
2103 {"Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 16,
2104 NULL, 0x0800,
2105 "Minimal encapsulation tunneled datagram support",
2106 HFILL}},
2108 {&hf_icmp_mip_g,
2109 {"GRE", "icmp.mip.g", FT_BOOLEAN, 16, NULL, 0x0400,
2110 "GRE encapsulated tunneled datagram support", HFILL}},
2112 {&hf_icmp_mip_v,
2113 {"VJ Comp", "icmp.mip.v", FT_BOOLEAN, 16, NULL, 0x0200,
2114 "Van Jacobson Header Compression Support", HFILL}},
2116 {&hf_icmp_mip_rt,
2117 {"Reverse tunneling", "icmp.mip.rt", FT_BOOLEAN, 16, NULL,
2118 0x0100,
2119 "Reverse tunneling support", HFILL}},
2121 {&hf_icmp_mip_u,
2122 {"UDP tunneling", "icmp.mip.u", FT_BOOLEAN, 16, NULL,
2123 0x0080,
2124 "UDP tunneling support", HFILL}},
2126 {&hf_icmp_mip_x,
2127 {"Revocation support", "icmp.mip.x", FT_BOOLEAN, 16, NULL,
2128 0x0040,
2129 "Registration revocation support", HFILL}},
2131 {&hf_icmp_mip_reserved,
2132 {"Reserved", "icmp.mip.reserved", FT_UINT16, BASE_HEX,
2133 NULL, 0x003f,
2134 NULL, HFILL}},
2136 {&hf_icmp_mip_coa,
2137 {"Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE,
2138 NULL, 0x0,
2139 NULL, HFILL}},
2141 {&hf_icmp_mip_challenge,
2142 {"Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE,
2143 NULL, 0x0,
2144 NULL, HFILL}},
2146 {&hf_icmp_mip_content,
2147 {"Content", "icmp.mip.content", FT_BYTES, BASE_NONE,
2148 NULL, 0x0,
2149 NULL, HFILL}},
2151 {&hf_icmp_ext,
2152 {"ICMP Extensions", "icmp.ext", FT_NONE, BASE_NONE, NULL,
2153 0x0,
2154 NULL, HFILL}},
2156 {&hf_icmp_ext_version,
2157 {"Version", "icmp.ext.version", FT_UINT8, BASE_DEC, NULL,
2158 0x0,
2159 NULL, HFILL}},
2161 {&hf_icmp_ext_reserved,
2162 {"Reserved", "icmp.ext.res", FT_UINT16, BASE_HEX, NULL,
2163 0x0fff,
2164 NULL, HFILL}},
2166 {&hf_icmp_ext_checksum,
2167 {"Checksum", "icmp.ext.checksum", FT_UINT16, BASE_HEX,
2168 NULL, 0x0,
2169 NULL, HFILL}},
2171 {&hf_icmp_ext_checksum_status,
2172 {"Checksum Status", "icmp.ext.checksum.status", FT_UINT8, BASE_NONE,
2173 VALS(proto_checksum_vals),
2174 0x0,
2175 NULL, HFILL}},
2177 {&hf_icmp_ext_length,
2178 {"Length", "icmp.ext.length", FT_UINT16, BASE_DEC, NULL,
2179 0x0,
2180 NULL, HFILL}},
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,
2188 0x0,
2189 NULL, HFILL}},
2191 {&hf_icmp_ext_data,
2192 {"Data", "icmp.ext.data", FT_BYTES, BASE_NONE, NULL, 0x0,
2193 NULL, HFILL}},
2195 {&hf_icmp_mpls_label,
2196 {"Label", "icmp.mpls.label", FT_UINT24, BASE_DEC, NULL,
2197 0xfffff0,
2198 NULL, HFILL}},
2200 {&hf_icmp_mpls_exp,
2201 {"Experimental", "icmp.mpls.exp", FT_UINT24, BASE_DEC,
2202 NULL, 0x0e,
2203 NULL, HFILL}},
2205 {&hf_icmp_mpls_s,
2206 {"Stack bit", "icmp.mpls.s", FT_BOOLEAN, 8,
2207 TFS(&tfs_set_notset), 0x01,
2208 NULL, HFILL}},
2210 {&hf_icmp_mpls_ttl,
2211 {"Time to live", "icmp.mpls.ttl", FT_UINT8, BASE_DEC,
2212 NULL, 0x0,
2213 NULL, HFILL}},
2215 {&hf_icmp_mpls_data,
2216 {"Data", "icmp.mpls.data", FT_BYTES, BASE_NONE ,
2217 NULL, 0x0,
2218 NULL, HFILL}},
2220 {&hf_icmp_resp_in,
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",
2224 HFILL}},
2226 {&hf_icmp_no_resp,
2227 {"No response seen", "icmp.no_resp", FT_NONE, BASE_NONE,
2228 NULL, 0x0,
2229 "No corresponding response frame was seen",
2230 HFILL}},
2232 {&hf_icmp_resp_to,
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}},
2237 {&hf_icmp_resptime,
2238 {"Response time", "icmp.resptime", FT_DOUBLE, BASE_NONE,
2239 NULL, 0x0,
2240 "The time between the request and the response, in ms.",
2241 HFILL}},
2243 {&hf_icmp_data_time,
2244 {"Timestamp from icmp data", "icmp.data_time",
2245 FT_ABSOLUTE_TIME,
2246 ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2247 "The timestamp in the first 8 or 16 bytes of the icmp data",
2248 HFILL}},
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",
2255 HFILL}},
2257 {&hf_icmp_length,
2258 {"Length", "icmp.length", FT_UINT8,
2259 BASE_DEC, NULL,
2260 0x0,
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,
2264 BASE_DEC, NULL,
2265 0x0,
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,
2271 NULL, HFILL}},
2272 {&hf_icmp_int_info_reserved,
2273 {"Reserved", "icmp.int_info.reserved",
2274 FT_UINT8, BASE_DEC, NULL, INT_INFO_RESERVED,
2275 NULL, HFILL}},
2276 {&hf_icmp_int_info_ifindex,
2277 {"ifIndex", "icmp.int_info.ifindex", FT_BOOLEAN, 8, NULL,
2278 INT_INFO_IFINDEX,
2279 "True: ifIndex of the interface included; False: ifIndex of the interface not included",
2280 HFILL}},
2281 {&hf_icmp_int_info_ipaddr,
2282 {"IP Address", "icmp.int_info.ipaddr", FT_BOOLEAN, 8,
2283 TFS(&tfs_present_not_present),
2284 INT_INFO_IPADDR,
2285 NULL, HFILL}},
2286 {&hf_icmp_int_info_name,
2287 {"Interface Name", "icmp.int_info.name_present", FT_BOOLEAN, 8,
2288 TFS(&tfs_present_not_present),
2289 INT_INFO_NAME,
2290 NULL,
2291 HFILL}},
2292 {&hf_icmp_int_info_mtu_present,
2293 {"MTU", "icmp.int_info.mtu_present", FT_BOOLEAN, 8, TFS(&tfs_present_not_present),
2294 INT_INFO_MTU,
2295 NULL, HFILL}},
2296 {&hf_icmp_int_info_index,
2297 {"Interface Index", "icmp.int_info.index",
2298 FT_UINT32, BASE_DEC,
2299 NULL, 0x0,
2300 NULL, HFILL}},
2301 {&hf_icmp_int_info_afi,
2302 {"Address Family Identifier", "icmp.int_info.afi",
2303 FT_UINT16, BASE_DEC,
2304 NULL, 0x0,
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,
2308 0x0,
2309 NULL, HFILL}},
2310 {&hf_icmp_int_info_ipv6,
2311 {"Source", "icmp.int_info.ipv6", FT_IPv6, BASE_NONE, NULL,
2312 0x0,
2313 NULL, HFILL}},
2314 {&hf_icmp_int_info_ipunknown,
2315 {"Source", "icmp.int_info.ipunknown", FT_BYTES, BASE_NONE, NULL,
2316 0x0,
2317 NULL, HFILL}},
2318 {&hf_icmp_int_info_name_length,
2319 {"Name Length", "icmp.int_info.name_length", FT_UINT8, BASE_DEC, NULL,
2320 0x0,
2321 NULL, HFILL}},
2322 {&hf_icmp_int_info_name_string,
2323 {"Name", "icmp.int_info.name", FT_STRING, BASE_NONE, NULL,
2324 0x0,
2325 NULL, HFILL}},
2326 {&hf_icmp_int_info_mtu,
2327 {"Maximum Transmission Unit", "icmp.int_info.mtu",
2328 FT_UINT32, BASE_DEC,
2329 NULL, 0x0,
2330 NULL, HFILL}},
2333 {&hf_icmp_ext_echo_seq_num,
2334 {"Sequence Number", "icmp.ext.echo.seq", FT_UINT8,
2335 BASE_DEC_HEX, NULL, 0x0,
2336 NULL, HFILL}},
2337 {&hf_icmp_ext_echo_req_reserved,
2338 {"Reserved", "icmp.ext.echo.req.res", FT_UINT8,
2339 BASE_HEX, NULL, 0xFE,
2340 NULL, HFILL}},
2341 {&hf_icmp_ext_echo_req_local,
2342 {"Local bit", "icmp.ext.echo.req.local", FT_BOOLEAN,
2343 8, TFS(&tfs_set_notset), 0x01,
2344 NULL, HFILL}},
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,
2348 NULL, HFILL}},
2349 {&hf_icmp_ext_echo_rsp_reserved,
2350 {"Reserved", "icmp.ext.echo.rsp.res", FT_UINT8,
2351 BASE_HEX, NULL, 0x18,
2352 NULL, HFILL}},
2353 {&hf_icmp_ext_echo_rsp_active,
2354 {"Active bit", "icmp.ext.echo.rsp.active", FT_BOOLEAN,
2355 8, TFS(&tfs_set_notset), 0x04,
2356 NULL, HFILL}},
2357 {&hf_icmp_ext_echo_rsp_ipv4,
2358 {"IPv4 bit", "icmp.ext.echo.rsp.ipv4", FT_BOOLEAN,
2359 8, TFS(&tfs_set_notset), 0x02,
2360 NULL, HFILL}},
2361 {&hf_icmp_ext_echo_rsp_ipv6,
2362 {"IPv6 bit", "icmp.ext.echo.rsp.ipv6", FT_BOOLEAN,
2363 8, TFS(&tfs_set_notset), 0x01,
2364 NULL, HFILL}},
2365 {&hf_icmp_int_ident_name_string,
2366 {"Name", "icmp.int_ident.name", FT_STRING,
2367 BASE_NONE, NULL, 0x0,
2368 NULL, HFILL}},
2369 {&hf_icmp_int_ident_index,
2370 {"Interface Index", "icmp.int_ident.index", FT_UINT32,
2371 BASE_DEC, NULL, 0x0,
2372 NULL, HFILL}},
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,
2380 NULL, HFILL}},
2381 {&hf_icmp_int_ident_reserved,
2382 {"Reserved", "icmp.int_ident.reserved", FT_BYTES,
2383 BASE_NONE, NULL, 0x0,
2384 NULL, HFILL}},
2385 {&hf_icmp_int_ident_ipv4,
2386 {"Address", "icmp.int_ident.ipv4", FT_IPv4,
2387 BASE_NONE, NULL, 0x0,
2388 NULL, HFILL}},
2389 {&hf_icmp_int_ident_ipv6,
2390 {"Address", "icmp.int_ident.ipv6", FT_IPv6,
2391 BASE_NONE, NULL, 0x0,
2392 NULL, HFILL}},
2393 {&hf_icmp_int_ident_address,
2394 {"Address", "icmp.int_ident.address", FT_BYTES,
2395 BASE_NONE, NULL, 0x0,
2396 NULL, HFILL}},
2400 static int *ett[] = {
2401 &ett_icmp,
2402 &ett_icmp_mip,
2403 &ett_icmp_mip_flags,
2404 /* MPLS extensions */
2405 &ett_icmp_ext,
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;
2424 proto_icmp =
2425 proto_register_protocol("Internet Control Message Protocol",
2426 "ICMP", "icmp");
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
2463 * Local variables:
2464 * c-basic-offset: 8
2465 * tab-width: 8
2466 * indent-tabs-mode: t
2467 * End:
2469 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2470 * :indentSize=8:tabSize=8:noTabs=false: