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 * (http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt
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 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 * Added support for ICMP extensions RFC 4884 and RFC 5837
30 * (c) 2011 Gaurav Tungatkar <gstungat@ncsu.edu>
40 #include <epan/packet.h>
41 #include <epan/ipproto.h>
42 #include <epan/prefs.h>
43 #include <epan/expert.h>
44 #include <epan/in_cksum.h>
45 #include <epan/to_str.h>
47 #include "packet-ip.h"
48 #include "packet-icmp.h"
49 #include <epan/conversation.h>
50 #include <epan/wmem/wmem.h>
53 void proto_register_icmp(void);
54 void proto_reg_handoff_icmp(void);
56 static int icmp_tap = -1;
58 /* Conversation related data */
59 static int hf_icmp_resp_in = -1;
60 static int hf_icmp_resp_to = -1;
61 static int hf_icmp_no_resp = -1;
62 static int hf_icmp_resptime = -1;
63 static int hf_icmp_data_time = -1;
64 static int hf_icmp_data_time_relative = -1;
66 typedef struct _icmp_conv_info_t {
67 wmem_tree_t *unmatched_pdus;
68 wmem_tree_t *matched_pdus;
71 static icmp_transaction_t *transaction_start(packet_info * pinfo,
74 static icmp_transaction_t *transaction_end(packet_info * pinfo,
78 /* Decode the end of the ICMP payload as ICMP MPLS extensions
79 if the packet in the payload has more than 128 bytes */
80 static gboolean favor_icmp_mpls_ext = FALSE;
83 static int hf_icmp_type = -1;
84 static int hf_icmp_code = -1;
85 static int hf_icmp_checksum = -1;
86 static int hf_icmp_checksum_bad = -1;
87 static int hf_icmp_ident = -1;
88 static int hf_icmp_ident_le = -1;
89 static int hf_icmp_seq_num = -1;
90 static int hf_icmp_seq_num_le = -1;
91 static int hf_icmp_mtu = -1;
92 static int hf_icmp_redir_gw = -1;
93 static int hf_icmp_length = -1;
96 static int hf_icmp_mip_type = -1;
97 static int hf_icmp_mip_length = -1;
98 static int hf_icmp_mip_prefix_length = -1;
99 static int hf_icmp_mip_seq = -1;
100 static int hf_icmp_mip_life = -1;
101 static int hf_icmp_mip_flags = -1;
102 static int hf_icmp_mip_r = -1;
103 static int hf_icmp_mip_b = -1;
104 static int hf_icmp_mip_h = -1;
105 static int hf_icmp_mip_f = -1;
106 static int hf_icmp_mip_m = -1;
107 static int hf_icmp_mip_g = -1;
108 static int hf_icmp_mip_v = -1;
109 static int hf_icmp_mip_rt = -1;
110 static int hf_icmp_mip_u = -1;
111 static int hf_icmp_mip_x = -1;
112 static int hf_icmp_mip_reserved = -1;
113 static int hf_icmp_mip_coa = -1;
114 static int hf_icmp_mip_challenge = -1;
116 /* extensions RFC 4884*/
117 static int hf_icmp_ext = -1;
118 static int hf_icmp_ext_version = -1;
119 static int hf_icmp_ext_reserved = -1;
120 static int hf_icmp_ext_checksum = -1;
121 static int hf_icmp_ext_checksum_bad = -1;
122 static int hf_icmp_ext_length = -1;
123 static int hf_icmp_ext_class = -1;
124 static int hf_icmp_ext_c_type = -1;
126 /* Interface information extension RFC 5837 */
127 static int hf_icmp_int_info_ifindex = -1;
128 static int hf_icmp_int_info_ipaddr = -1;
129 static int hf_icmp_int_info_name = -1;
130 static int hf_icmp_int_info_mtu = -1;
131 static int hf_icmp_int_info_afi = -1;
132 static int hf_icmp_int_info_ipv4 = -1;
133 static int hf_icmp_int_info_ipv6 = -1;
134 static int hf_icmp_int_info_role = -1;
135 static int hf_icmp_int_info_reserved = -1;
136 static gint ett_icmp_interface_info_object = -1;
137 static gint ett_icmp_interface_ipaddr = -1;
138 static gint ett_icmp_interface_name = -1;
139 /* MPLS extension object*/
140 static int hf_icmp_mpls_label = -1;
141 static int hf_icmp_mpls_exp = -1;
142 static int hf_icmp_mpls_s = -1;
143 static int hf_icmp_mpls_ttl = -1;
145 static gint ett_icmp = -1;
146 static gint ett_icmp_mip = -1;
147 static gint ett_icmp_mip_flags = -1;
150 static gint ett_icmp_ext = -1;
151 static gint ett_icmp_ext_object = -1;
153 /* MPLS extensions */
154 static gint ett_icmp_mpls_stack_object = -1;
156 static expert_field ei_icmp_resp_not_found = EI_INIT;
159 /* ICMP definitions */
160 #define ICMP_ECHOREPLY 0
161 #define ICMP_UNREACH 3
162 #define ICMP_SOURCEQUENCH 4
163 #define ICMP_REDIRECT 5
164 #define ICMP_ALTHOST 6
166 #define ICMP_RTRADVERT 9
167 #define ICMP_RTRSOLICIT 10
168 #define ICMP_TIMXCEED 11
169 #define ICMP_PARAMPROB 12
170 #define ICMP_TSTAMP 13
171 #define ICMP_TSTAMPREPLY 14
173 #define ICMP_IREQREPLY 16
174 #define ICMP_MASKREQ 17
175 #define ICMP_MASKREPLY 18
176 #define ICMP_PHOTURIS 40
178 /* ICMP UNREACHABLE */
179 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
180 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
181 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
182 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
183 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
184 #define ICMP_SR_FAILED 5 /* Source Route failed */
185 #define ICMP_NET_UNKNOWN 6
186 #define ICMP_HOST_UNKNOWN 7
187 #define ICMP_HOST_ISOLATED 8
188 #define ICMP_NET_ANO 9
189 #define ICMP_HOST_ANO 10
190 #define ICMP_NET_UNR_TOS 11
191 #define ICMP_HOST_UNR_TOS 12
192 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
193 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
194 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
196 #define ICMP_MIP_EXTENSION_PAD 0
197 #define ICMP_MIP_MOB_AGENT_ADV 16
198 #define ICMP_MIP_PREFIX_LENGTHS 19
199 #define ICMP_MIP_CHALLENGE 24
201 static dissector_handle_t ip_handle;
202 static dissector_handle_t data_handle;
204 static const value_string icmp_type_str[] = {
205 {ICMP_ECHOREPLY, "Echo (ping) reply"},
208 {ICMP_UNREACH, "Destination unreachable"},
209 {ICMP_SOURCEQUENCH, "Source quench (flow control)"},
210 {ICMP_REDIRECT, "Redirect"},
211 {ICMP_ALTHOST, "Alternate host address"},
212 {ICMP_ECHO, "Echo (ping) request"},
213 {ICMP_RTRADVERT, "Router advertisement"},
214 {ICMP_RTRSOLICIT, "Router solicitation"},
215 {ICMP_TIMXCEED, "Time-to-live exceeded"},
216 {ICMP_PARAMPROB, "Parameter problem"},
217 {ICMP_TSTAMP, "Timestamp request"},
218 {ICMP_TSTAMPREPLY, "Timestamp reply"},
219 {ICMP_IREQ, "Information request"},
220 {ICMP_IREQREPLY, "Information reply"},
221 {ICMP_MASKREQ, "Address mask request"},
222 {ICMP_MASKREPLY, "Address mask reply"},
223 {19, "Reserved (for security)"},
225 {31, "Datagram Conversion Error"},
226 {32, "Mobile Host Redirect"},
227 {33, "IPv6 Where-Are-You"},
228 {34, "IPv6 I-Am-Here"},
229 {35, "Mobile Registration Request"},
230 {36, "Mobile Registration Reply"},
231 {37, "Domain Name Request"},
232 {38, "Domain Name Reply"},
234 {ICMP_PHOTURIS, "Photuris"},
235 {41, "Experimental mobility protocols"},
239 static const value_string unreach_code_str[] = {
240 {ICMP_NET_UNREACH, "Network unreachable"},
241 {ICMP_HOST_UNREACH, "Host unreachable"},
242 {ICMP_PROT_UNREACH, "Protocol unreachable"},
243 {ICMP_PORT_UNREACH, "Port unreachable"},
244 {ICMP_FRAG_NEEDED, "Fragmentation needed"},
245 {ICMP_SR_FAILED, "Source route failed"},
246 {ICMP_NET_UNKNOWN, "Destination network unknown"},
247 {ICMP_HOST_UNKNOWN, "Destination host unknown"},
248 {ICMP_HOST_ISOLATED, "Source host isolated"},
249 {ICMP_NET_ANO, "Network administratively prohibited"},
250 {ICMP_HOST_ANO, "Host administratively prohibited"},
251 {ICMP_NET_UNR_TOS, "Network unreachable for TOS"},
252 {ICMP_HOST_UNR_TOS, "Host unreachable for TOS"},
253 {ICMP_PKT_FILTERED, "Communication administratively filtered"},
254 {ICMP_PREC_VIOLATION, "Host precedence violation"},
255 {ICMP_PREC_CUTOFF, "Precedence cutoff in effect"},
259 static const value_string redir_code_str[] = {
260 {0, "Redirect for network"},
261 {1, "Redirect for host"},
262 {2, "Redirect for TOS and network"},
263 {3, "Redirect for TOS and host"},
267 static const value_string alt_host_code_str[] = {
268 {0, "Alternate address for host"},
272 static const value_string rtradvert_code_str[] = {
273 {0, "Normal router advertisement"},
274 {16, "Does not route common traffic"},
278 static const value_string ttl_code_str[] = {
279 {0, "Time to live exceeded in transit"},
280 {1, "Fragment reassembly time exceeded"},
284 static const value_string par_code_str[] = {
285 {0, "Pointer indicates the error"},
286 {1, "Required option missing"},
291 static const value_string photuris_code_str[] = {
293 {1, "Authentication Failed"},
294 {2, "Decompression Failed"},
295 {3, "Decryption Failed"},
296 {4, "Need Authentication"},
297 {5, "Need Authorization"},
301 static const value_string mip_extensions[] = {
302 {ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
303 {ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
305 {ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
306 {ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
310 /* RFC 5837 ICMP extension - Interface Information Object
313 static const value_string interface_role_str[] = {
314 {0, "IP interface upon which datagram arrived"},
316 "sub-IP component of an IP interface upon which datagram arrived"},
317 {2, "IP interface through which datagram would be forwarded"},
318 {3, "IP next-hop to which datagram would be forwarded"},
322 #define INT_INFO_INTERFACE_ROLE 0xc0
323 #define INT_INFO_RESERVED 0x30
324 #define INT_INFO_IFINDEX 0x08
325 #define INT_INFO_IPADDR 0x04
326 #define INT_INFO_NAME 0x02
327 #define INT_INFO_MTU 0x01
329 #define INTERFACE_INFORMATION_OBJECT_CLASS 2
331 #define MPLS_STACK_ENTRY_OBJECT_CLASS 1
332 #define MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS 0
334 #define MPLS_STACK_ENTRY_C_TYPE 1
335 #define MPLS_EXTENDED_PAYLOAD_C_TYPE 1
337 #define INET6_ADDRLEN 16
339 static conversation_t *_find_or_create_conversation(packet_info * pinfo)
341 conversation_t *conv = NULL;
343 /* Have we seen this conversation before? */
345 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
346 pinfo->ptype, 0, 0, 0);
348 /* No, this is a new conversation. */
350 conversation_new(pinfo->fd->num, &pinfo->src,
351 &pinfo->dst, pinfo->ptype, 0, 0, 0);
357 * Dissect the mobile ip advertisement extensions.
360 dissect_mip_extensions(tvbuff_t * tvb, int offset, proto_tree * tree)
366 proto_tree *mip_tree = NULL;
367 proto_tree *flags_tree = NULL;
371 /* Not much to do if we're not parsing everything */
375 while (tvb_reported_length_remaining(tvb, offset) > 0) {
376 type = tvb_get_guint8(tvb, offset + 0);
378 length = tvb_get_guint8(tvb, offset + 1);
383 mip_tree = proto_tree_add_subtree_format(tree, tvb, offset,
384 1, ett_icmp_mip, &ti,
385 "Ext: %s", val_to_str(type,
388 proto_tree_add_item(mip_tree, hf_icmp_mip_type,
392 if (type != ICMP_MIP_EXTENSION_PAD)
394 proto_item_set_len(ti, length + 2);
397 proto_tree_add_item(mip_tree, hf_icmp_mip_length,
404 case ICMP_MIP_EXTENSION_PAD:
405 /* One byte padding extension */
407 case ICMP_MIP_MOB_AGENT_ADV:
408 /* Mobility Agent Advertisement Extension (RFC 2002) */
410 /* sequence number */
411 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb,
412 offset, 2, ENC_BIG_ENDIAN);
414 /* Registration Lifetime */
415 proto_tree_add_item(mip_tree, hf_icmp_mip_life,
420 flags = tvb_get_ntohs(tvb, offset);
421 ti = proto_tree_add_uint(mip_tree,
422 hf_icmp_mip_flags, tvb,
425 proto_item_add_subtree(ti, ett_icmp_mip_flags);
426 proto_tree_add_boolean(flags_tree, hf_icmp_mip_r,
427 tvb, offset, 2, flags);
428 proto_tree_add_boolean(flags_tree, hf_icmp_mip_b,
429 tvb, offset, 2, flags);
430 proto_tree_add_boolean(flags_tree, hf_icmp_mip_h,
431 tvb, offset, 2, flags);
432 proto_tree_add_boolean(flags_tree, hf_icmp_mip_f,
433 tvb, offset, 2, flags);
434 proto_tree_add_boolean(flags_tree, hf_icmp_mip_m,
435 tvb, offset, 2, flags);
436 proto_tree_add_boolean(flags_tree, hf_icmp_mip_g,
437 tvb, offset, 2, flags);
438 proto_tree_add_boolean(flags_tree, hf_icmp_mip_v,
439 tvb, offset, 2, flags);
440 proto_tree_add_boolean(flags_tree, hf_icmp_mip_rt,
441 tvb, offset, 2, flags);
442 proto_tree_add_boolean(flags_tree, hf_icmp_mip_u,
443 tvb, offset, 2, flags);
444 proto_tree_add_boolean(flags_tree, hf_icmp_mip_x,
445 tvb, offset, 2, flags);
448 proto_tree_add_uint(flags_tree,
449 hf_icmp_mip_reserved, tvb,
454 numCOAs = (length - 6) / 4;
455 for (i = 0; i < numCOAs; i++) {
456 proto_tree_add_item(mip_tree,
457 hf_icmp_mip_coa, tvb,
463 case ICMP_MIP_PREFIX_LENGTHS:
464 /* Prefix-Lengths Extension (RFC 2002) */
468 for (i = 0; i < length; i++) {
469 proto_tree_add_item(mip_tree,
470 hf_icmp_mip_prefix_length,
476 case ICMP_MIP_CHALLENGE:
477 /* Challenge Extension (RFC 3012) */
479 proto_tree_add_item(mip_tree,
480 hf_icmp_mip_challenge, tvb,
481 offset, length, ENC_NA);
488 proto_tree_add_text(mip_tree, tvb, offset,
497 } /* dissect_mip_extensions */
500 dissect_mpls_extended_payload_object(tvbuff_t * tvb, gint offset,
501 proto_tree * ext_object_tree,
502 proto_item * tf_object)
505 guint16 obj_length, obj_trunc_length;
506 gboolean unknown_object;
508 unknown_object = FALSE;
510 obj_length = tvb_get_ntohs(tvb, offset);
513 MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
516 c_type = tvb_get_guint8(tvb, offset + 3);
517 proto_tree_add_uint(ext_object_tree, hf_icmp_ext_c_type, tvb,
518 offset + 3, 1, c_type);
520 /* skip the object header */
524 case MPLS_EXTENDED_PAYLOAD_C_TYPE:
525 proto_item_set_text(tf_object, "Extended Payload");
527 /* This object contains some portion of the original packet
528 that could not fit in the 128 bytes of the ICMP payload */
529 if (obj_trunc_length > 4) {
530 proto_tree_add_text(ext_object_tree, tvb,
531 offset, obj_trunc_length - 4,
533 obj_trunc_length - 4);
537 unknown_object = TRUE;
538 } /* end switch c_type */
539 return unknown_object;
543 dissect_mpls_stack_entry_object(tvbuff_t * tvb, gint offset,
544 proto_tree * ext_object_tree,
545 proto_item * tf_object)
548 proto_item *tf_entry;
549 proto_tree *mpls_stack_object_tree;
550 guint16 obj_length, obj_trunc_length;
555 gboolean unknown_object;
557 unknown_object = FALSE;
559 obj_length = tvb_get_ntohs(tvb, offset);
562 MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
563 obj_end_offset = offset + obj_trunc_length;
565 c_type = tvb_get_guint8(tvb, offset + 3);
566 proto_tree_add_uint(ext_object_tree, hf_icmp_ext_c_type, tvb,
567 offset + 3, 1, c_type);
569 /* skip the object header */
573 case MPLS_STACK_ENTRY_C_TYPE:
574 proto_item_set_text(tf_object, "MPLS Stack Entry");
576 while (offset + 4 <= obj_end_offset) {
577 if (tvb_reported_length_remaining(tvb, offset) < 4) {
578 /* Not enough room in the packet ! */
581 /* Create a subtree for each entry (the text will be set later) */
582 mpls_stack_object_tree = proto_tree_add_subtree(ext_object_tree,
584 ett_icmp_mpls_stack_object, &tf_entry, " ");
587 label = (guint) tvb_get_ntohs(tvb, offset);
588 tmp = tvb_get_guint8(tvb, offset + 2);
589 label = (label << 4) + (tmp >> 4);
591 proto_tree_add_uint(mpls_stack_object_tree,
592 hf_icmp_mpls_label, tvb,
593 offset, 3, label << 4);
595 proto_item_set_text(tf_entry, "Label: %u", label);
597 /* Experimental field (also called "CoS") */
598 proto_tree_add_uint(mpls_stack_object_tree,
599 hf_icmp_mpls_exp, tvb,
602 proto_item_append_text(tf_entry, ", Exp: %u",
606 proto_tree_add_boolean(mpls_stack_object_tree,
610 proto_item_append_text(tf_entry, ", S: %u",
614 ttl = tvb_get_guint8(tvb, offset + 3);
616 proto_tree_add_item(mpls_stack_object_tree,
617 hf_icmp_mpls_ttl, tvb,
618 offset + 3, 1, ENC_BIG_ENDIAN);
620 proto_item_append_text(tf_entry, ", TTL: %u", ttl);
626 if (offset < obj_end_offset) {
627 proto_tree_add_text(ext_object_tree, tvb, offset,
628 obj_end_offset - offset,
630 obj_end_offset - offset);
636 unknown_object = TRUE;
639 } /* end switch c_type */
640 return unknown_object;
642 } /* end dissect_mpls_stack_entry_object */
644 /* Dissect Interface Information Object RFC 5837*/
646 dissect_interface_information_object(tvbuff_t * tvb, gint offset,
647 proto_tree * ext_object_tree,
648 proto_item * tf_object)
650 proto_tree *int_name_object_tree = NULL;
651 proto_tree *int_ipaddr_object_tree;
652 guint16 obj_length, obj_trunc_length;
655 gboolean unknown_object;
656 guint8 if_index_flag;
661 struct e_in6_addr ipaddr_v6;
662 guint8 int_name_length = 0;
664 unknown_object = FALSE;
666 obj_length = tvb_get_ntohs(tvb, offset);
669 MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
670 obj_end_offset = offset + obj_trunc_length;
673 c_type = tvb_get_guint8(tvb, offset + 3);
675 proto_item_set_text(tf_object, "Interface Information Object");
676 if (tvb_reported_length_remaining(tvb, offset) < 4) {
677 /* Not enough room in the packet ! return unknown_object = TRUE */
681 if_index_flag = (c_type & INT_INFO_IFINDEX) >> 3;
682 ipaddr_flag = (c_type & INT_INFO_IPADDR) >> 2;
683 name_flag = (c_type & INT_INFO_NAME) >> 1;
686 static const gint *c_type_fields[] = {
687 &hf_icmp_int_info_role,
688 &hf_icmp_int_info_reserved,
689 &hf_icmp_int_info_ifindex,
690 &hf_icmp_int_info_ipaddr,
691 &hf_icmp_int_info_name,
692 &hf_icmp_int_info_mtu,
695 proto_tree_add_bitmask(ext_object_tree, tvb, offset + 3,
697 ett_icmp_interface_info_object,
698 c_type_fields, ENC_BIG_ENDIAN);
704 /*if ifIndex is set, next 32 bits are ifIndex */
706 if (obj_end_offset >= offset + 4) {
707 if_index = tvb_get_ntohl(tvb, offset);
708 proto_tree_add_text(ext_object_tree,
710 "Interface Index: %u",
714 proto_tree_add_text(ext_object_tree,
716 "Interface Index:(truncated)");
721 /* IP Address Sub Object */
722 if (ipaddr_flag && (obj_end_offset >= offset + 2)) {
723 /* Address Family Identifier */
724 afi = tvb_get_ntohs(tvb, offset);
727 * if afi = 1, IPv4 address, 2 bytes afi, 2 bytes rsvd, 4 bytes IP addr
728 * if afi = 2, IPv6 address, 2 bytes afi, 2 bytes rsvd, 6 bytes IP addr
730 int_ipaddr_object_tree = proto_tree_add_subtree(ext_object_tree, tvb, offset,
731 afi == 1 ? 8 : 10, ett_icmp_interface_ipaddr, NULL,
732 "IP Address Sub-Object");
734 proto_tree_add_uint(int_ipaddr_object_tree,
735 hf_icmp_int_info_afi, tvb, offset, 2,
740 if (afi == 1 && (obj_end_offset >= offset + 4)) {
741 proto_tree_add_ipv4(int_ipaddr_object_tree,
742 hf_icmp_int_info_ipv4, tvb,
743 offset, 4, tvb_get_ntohl(tvb,
747 && (obj_end_offset >= offset + INET6_ADDRLEN)) {
748 tvb_get_ipv6(tvb, offset, &ipaddr_v6);
749 proto_tree_add_ipv6(int_ipaddr_object_tree,
750 hf_icmp_int_info_ipv6, tvb,
751 offset, INET6_ADDRLEN,
752 (guint8 *) & ipaddr_v6);
753 offset += INET6_ADDRLEN;
755 proto_tree_add_text(int_ipaddr_object_tree, tvb,
757 offset - obj_end_offset,
763 /* Interface Name Sub Object */
765 if (obj_end_offset >= offset + 1) {
766 int_name_length = tvb_get_guint8(tvb, offset);
767 int_name_object_tree = proto_tree_add_subtree(ext_object_tree, tvb,
768 offset, int_name_length, ett_icmp_interface_name, NULL,
769 "Interface Name Sub-Object");
771 proto_tree_add_text(int_name_object_tree, tvb,
772 offset, 1, "Length: %u",
775 if (obj_end_offset >= offset + 1 + int_name_length) {
777 proto_tree_add_text(int_name_object_tree, tvb,
778 offset + 1, int_name_length,
779 "Interface Name: %s",
780 tvb_format_text(tvb, offset + 1, int_name_length));
785 return unknown_object;
787 } /*end dissect_interface_information_object */
790 dissect_extensions(tvbuff_t * tvb, gint offset, proto_tree * tree)
795 guint16 cksum, computed_cksum;
796 guint16 obj_length, obj_trunc_length;
797 proto_item *ti, *tf_object, *hidden_item;
798 proto_tree *ext_tree, *ext_object_tree;
800 guint reported_length;
801 gboolean unknown_object;
802 guint8 int_info_obj_count;
808 int_info_obj_count = 0;
810 reported_length = tvb_reported_length_remaining(tvb, offset);
812 if (reported_length < 4 /* Common header */ ) {
813 proto_tree_add_text(tree, tvb, offset,
815 "ICMP Multi-Part Extensions (truncated)");
819 /* Add a tree for multi-part extensions RFC 4884 */
820 ti = proto_tree_add_none_format(tree, hf_icmp_ext, tvb,
821 offset, reported_length,
822 "ICMP Multi-Part Extensions");
824 ext_tree = proto_item_add_subtree(ti, ett_icmp_ext);
827 version = hi_nibble(tvb_get_guint8(tvb, offset));
828 proto_tree_add_uint(ext_tree, hf_icmp_ext_version, tvb, offset, 1,
832 proto_tree_add_item(ext_tree, hf_icmp_ext_reserved,
833 tvb, offset, 2, ENC_BIG_ENDIAN);
836 cksum = tvb_get_ntohs(tvb, offset + 2);
839 ip_checksum(tvb_get_ptr(tvb, offset, reported_length),
842 if (computed_cksum == 0) {
843 proto_tree_add_uint_format_value(ext_tree, hf_icmp_ext_checksum,
844 tvb, offset + 2, 2, cksum,
848 proto_tree_add_boolean(ext_tree,
849 hf_icmp_ext_checksum_bad, tvb,
850 offset + 2, 2, FALSE);
852 proto_tree_add_uint_format_value(ext_tree, hf_icmp_ext_checksum,
853 tvb, offset + 2, 2, cksum,
854 "0x%04x [incorrect, should be 0x%04x]",
855 cksum, in_cksum_shouldbe(cksum,
858 proto_tree_add_boolean(ext_tree,
859 hf_icmp_ext_checksum_bad, tvb,
860 offset + 2, 2, TRUE);
862 PROTO_ITEM_SET_HIDDEN(hidden_item);
864 if (version != 1 && version != 2) {
865 /* Unsupported version */
866 proto_item_append_text(ti, " (unsupported version)");
870 /* Skip the common header */
873 /* While there is enough room to read an object */
874 while (tvb_reported_length_remaining(tvb, offset) >=
875 4 /* Object header */ ) {
877 obj_length = tvb_get_ntohs(tvb, offset);
881 tvb_reported_length_remaining(tvb, offset));
883 obj_end_offset = offset + obj_trunc_length;
885 /* Add a subtree for this object (the text will be reset later) */
886 ext_object_tree = proto_tree_add_subtree(ext_tree, tvb, offset,
887 MAX(obj_trunc_length, 4),
888 ett_icmp_ext_object, &tf_object, "Unknown object");
890 proto_tree_add_uint(ext_object_tree, hf_icmp_ext_length,
891 tvb, offset, 2, obj_length);
894 class_num = tvb_get_guint8(tvb, offset + 2);
895 proto_tree_add_uint(ext_object_tree, hf_icmp_ext_class,
896 tvb, offset + 2, 1, class_num);
899 c_type = tvb_get_guint8(tvb, offset + 3);
901 if (obj_length < 4 /* Object header */ ) {
902 /* Thanks doc/README.developer :)) */
903 proto_item_set_text(tf_object,
904 "Object with bad length");
910 case MPLS_STACK_ENTRY_OBJECT_CLASS:
912 dissect_mpls_stack_entry_object(tvb, offset,
916 case INTERFACE_INFORMATION_OBJECT_CLASS:
918 dissect_interface_information_object(tvb,
922 int_info_obj_count++;
923 if (int_info_obj_count > 4) {
924 proto_item_set_text(tf_object,
925 "More than 4 Interface Information Objects");
928 case MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS:
930 dissect_mpls_extended_payload_object(tvb,
937 unknown_object = TRUE;
940 } /* end switch class_num */
942 /* Skip the object header */
945 /* The switches couldn't decode the object */
946 if (unknown_object == TRUE) {
947 proto_item_set_text(tf_object,
948 "Unknown object (%d/%d)",
951 if (obj_trunc_length > 4) {
952 proto_tree_add_text(ext_object_tree, tvb,
954 obj_trunc_length - 4,
956 obj_trunc_length - 4);
961 if (obj_trunc_length < obj_length) {
962 proto_item_append_text(tf_object, " (truncated)");
965 /* Go to the end of the object */
966 offset = obj_end_offset;
972 /* ======================================================================= */
973 static icmp_transaction_t *transaction_start(packet_info * pinfo,
977 conversation_t *conversation;
978 icmp_conv_info_t *icmp_info;
979 icmp_transaction_t *icmp_trans;
980 wmem_tree_key_t icmp_key[3];
983 /* Handle the conversation tracking */
984 conversation = _find_or_create_conversation(pinfo);
985 icmp_info = (icmp_conv_info_t *)conversation_get_proto_data(conversation, proto_icmp);
986 if (icmp_info == NULL) {
987 icmp_info = wmem_new(wmem_file_scope(), icmp_conv_info_t);
988 icmp_info->unmatched_pdus = wmem_tree_new(wmem_file_scope());
989 icmp_info->matched_pdus = wmem_tree_new(wmem_file_scope());
990 conversation_add_proto_data(conversation, proto_icmp,
994 if (!PINFO_FD_VISITED(pinfo)) {
995 /* this is a new request, create a new transaction structure and map it to the
998 icmp_key[0].length = 2;
999 icmp_key[0].key = key;
1000 icmp_key[1].length = 0;
1001 icmp_key[1].key = NULL;
1003 icmp_trans = wmem_new(wmem_file_scope(), icmp_transaction_t);
1004 icmp_trans->rqst_frame = PINFO_FD_NUM(pinfo);
1005 icmp_trans->resp_frame = 0;
1006 icmp_trans->rqst_time = pinfo->fd->abs_ts;
1007 nstime_set_zero(&icmp_trans->resp_time);
1008 wmem_tree_insert32_array(icmp_info->unmatched_pdus, icmp_key,
1009 (void *) icmp_trans);
1011 /* Already visited this frame */
1012 guint32 frame_num = pinfo->fd->num;
1014 icmp_key[0].length = 2;
1015 icmp_key[0].key = key;
1016 icmp_key[1].length = 1;
1017 icmp_key[1].key = &frame_num;
1018 icmp_key[2].length = 0;
1019 icmp_key[2].key = NULL;
1022 (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->matched_pdus,
1025 if (icmp_trans == NULL) {
1026 if (PINFO_FD_VISITED(pinfo)) {
1027 /* No response found - add field and expert info */
1028 it = proto_tree_add_item(tree, hf_icmp_no_resp, NULL, 0, 0,
1030 PROTO_ITEM_SET_GENERATED(it);
1032 col_append_fstr(pinfo->cinfo, COL_INFO, " (no response found!)");
1034 /* Expert info. TODO: add to _icmp_transaction_t type and sequence number
1035 so can report here (and in taps) */
1036 expert_add_info_format(pinfo, it, &ei_icmp_resp_not_found,
1037 "No response seen to ICMP request in frame %u",
1044 /* Print state tracking in the tree */
1045 if (icmp_trans->resp_frame) {
1046 it = proto_tree_add_uint(tree, hf_icmp_resp_in, NULL, 0, 0,
1047 icmp_trans->resp_frame);
1048 PROTO_ITEM_SET_GENERATED(it);
1050 col_append_fstr(pinfo->cinfo, COL_INFO, " (reply in %d)",
1051 icmp_trans->resp_frame);
1056 } /* transaction_start() */
1058 /* ======================================================================= */
1059 static icmp_transaction_t *transaction_end(packet_info * pinfo,
1063 conversation_t *conversation;
1064 icmp_conv_info_t *icmp_info;
1065 icmp_transaction_t *icmp_trans;
1066 wmem_tree_key_t icmp_key[3];
1072 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1073 pinfo->ptype, 0, 0, 0);
1074 if (conversation == NULL) {
1078 icmp_info = (icmp_conv_info_t *)conversation_get_proto_data(conversation, proto_icmp);
1079 if (icmp_info == NULL) {
1083 if (!PINFO_FD_VISITED(pinfo)) {
1086 icmp_key[0].length = 2;
1087 icmp_key[0].key = key;
1088 icmp_key[1].length = 0;
1089 icmp_key[1].key = NULL;
1091 (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->unmatched_pdus,
1093 if (icmp_trans == NULL) {
1097 /* we have already seen this response, or an identical one */
1098 if (icmp_trans->resp_frame != 0) {
1102 icmp_trans->resp_frame = PINFO_FD_NUM(pinfo);
1104 /* we found a match. Add entries to the matched table for both request and reply frames
1106 icmp_key[0].length = 2;
1107 icmp_key[0].key = key;
1108 icmp_key[1].length = 1;
1109 icmp_key[1].key = &frame_num;
1110 icmp_key[2].length = 0;
1111 icmp_key[2].key = NULL;
1113 frame_num = icmp_trans->rqst_frame;
1114 wmem_tree_insert32_array(icmp_info->matched_pdus, icmp_key,
1115 (void *) icmp_trans);
1117 frame_num = icmp_trans->resp_frame;
1118 wmem_tree_insert32_array(icmp_info->matched_pdus, icmp_key,
1119 (void *) icmp_trans);
1121 /* Already visited this frame */
1122 guint32 frame_num = pinfo->fd->num;
1124 icmp_key[0].length = 2;
1125 icmp_key[0].key = key;
1126 icmp_key[1].length = 1;
1127 icmp_key[1].key = &frame_num;
1128 icmp_key[2].length = 0;
1129 icmp_key[2].key = NULL;
1132 (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->matched_pdus,
1135 if (icmp_trans == NULL) {
1141 it = proto_tree_add_uint(tree, hf_icmp_resp_to, NULL, 0, 0,
1142 icmp_trans->rqst_frame);
1143 PROTO_ITEM_SET_GENERATED(it);
1145 nstime_delta(&ns, &pinfo->fd->abs_ts, &icmp_trans->rqst_time);
1146 icmp_trans->resp_time = ns;
1147 resp_time = nstime_to_msec(&ns);
1148 it = proto_tree_add_double_format_value(tree, hf_icmp_resptime,
1149 NULL, 0, 0, resp_time,
1150 "%.3f ms", resp_time);
1151 PROTO_ITEM_SET_GENERATED(it);
1153 col_append_fstr(pinfo->cinfo, COL_INFO, " (request in %d)",
1154 icmp_trans->rqst_frame);
1158 } /* transaction_end() */
1160 #define MSPERDAY 86400000
1162 /* ======================================================================= */
1164 get_best_guess_mstimeofday(tvbuff_t * tvb, gint offset, guint32 comp_ts)
1166 guint32 be_ts, le_ts;
1168 /* Account for the special case from RFC 792 as best we can by clearing
1169 * the msb. Ref: [Page 16] of http://tools.ietf.org/html/rfc792:
1171 If the time is not available in milliseconds or cannot be provided
1172 with respect to midnight UT then any time can be inserted in a
1173 timestamp provided the high order bit of the timestamp is also set
1174 to indicate this non-standard value.
1176 be_ts = tvb_get_ntohl(tvb, offset) & 0x7fffffff;
1177 le_ts = tvb_get_letohl(tvb, offset) & 0x7fffffff;
1179 if (be_ts < MSPERDAY && le_ts >= MSPERDAY) {
1183 if (le_ts < MSPERDAY && be_ts >= MSPERDAY) {
1187 if (be_ts < MSPERDAY && le_ts < MSPERDAY) {
1188 guint32 saved_be_ts = be_ts;
1189 guint32 saved_le_ts = le_ts;
1191 /* Is this a rollover to a new day, clocks not synchronized, different
1192 * timezones between originate and receive/transmit, .. what??? */
1193 if (be_ts < comp_ts && be_ts <= (MSPERDAY / 4)
1194 && comp_ts >= (MSPERDAY - (MSPERDAY / 4)))
1195 be_ts += MSPERDAY; /* Assume a rollover to a new day */
1196 if (le_ts < comp_ts && le_ts <= (MSPERDAY / 4)
1197 && comp_ts >= (MSPERDAY - (MSPERDAY / 4)))
1198 le_ts += MSPERDAY; /* Assume a rollover to a new day */
1199 if ((be_ts - comp_ts) < (le_ts - comp_ts))
1204 /* Both are bigger than MSPERDAY, but neither one's msb's are set. This
1205 * is clearly invalid, but now what TODO? For now, take the one closest to
1206 * the comparative timestamp, which is another way of saying, "let's
1207 * return a deterministic wild guess. */
1208 if ((be_ts - comp_ts) < (le_ts - comp_ts)) {
1212 } /* get_best_guess_mstimeofday() */
1215 * RFC 792 for basic ICMP.
1216 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1217 * RFC 1256 for router discovery messages.
1218 * RFC 2002 and 3012 for Mobile IP stuff.
1221 dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data)
1223 proto_tree *icmp_tree = NULL;
1227 guint8 icmp_original_dgram_length;
1228 guint length, reported_length;
1229 guint16 cksum, computed_cksum;
1230 const gchar *type_str, *code_str;
1231 guint8 num_addrs = 0;
1232 guint8 addr_entry_size = 0;
1234 gboolean save_in_error_pkt;
1237 guint32 conv_key[2];
1238 icmp_transaction_t *trans = NULL;
1239 nstime_t ts, time_relative;
1240 ws_ip *iph = (ws_ip*)data;
1242 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1243 col_clear(pinfo->cinfo, COL_INFO);
1245 /* To do: check for runts, errs, etc. */
1246 icmp_type = tvb_get_guint8(tvb, 0);
1247 icmp_code = tvb_get_guint8(tvb, 1);
1248 cksum = tvb_get_ntohs(tvb, 2);
1249 /*length of original datagram carried in the ICMP payload. In terms of 32 bit
1251 icmp_original_dgram_length = tvb_get_guint8(tvb, 5);
1254 val_to_str_const(icmp_type, icmp_type_str,
1255 "Unknown ICMP (obsolete or malformed?)");
1257 switch (icmp_type) {
1260 val_to_str(icmp_code, unreach_code_str,
1261 "Unknown code: %u");
1265 val_to_str(icmp_code, redir_code_str,
1266 "Unknown code: %u");
1270 val_to_str(icmp_code, alt_host_code_str,
1271 "Unknown code: %u");
1273 case ICMP_RTRADVERT:
1274 switch (icmp_code) {
1275 case 0: /* Mobile-Ip */
1276 case 16: /* Mobile-Ip */
1277 type_str = "Mobile IP Advertisement";
1279 } /* switch icmp_code */
1281 val_to_str(icmp_code, rtradvert_code_str,
1282 "Unknown code: %u");
1286 val_to_str(icmp_code, ttl_code_str,
1287 "Unknown code: %u");
1289 case ICMP_PARAMPROB:
1291 val_to_str(icmp_code, par_code_str,
1292 "Unknown code: %u");
1296 val_to_str(icmp_code, photuris_code_str,
1297 "Unknown code: %u");
1304 col_add_fstr(pinfo->cinfo, COL_INFO, "%-20s", type_str);
1306 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", code_str);
1309 length = tvb_length(tvb);
1310 reported_length = tvb_reported_length(tvb);
1312 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, ENC_NA);
1313 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1315 ti = proto_tree_add_item(icmp_tree, hf_icmp_type, tvb, 0, 1,
1317 proto_item_append_text(ti, " (%s)", type_str);
1319 ti = proto_tree_add_item(icmp_tree, hf_icmp_code, tvb, 1, 1,
1322 proto_item_append_text(ti, " (%s)", code_str);
1325 if (!pinfo->fragmented && length >= reported_length
1326 && !pinfo->flags.in_error_pkt) {
1327 /* The packet isn't part of a fragmented datagram, isn't
1328 truncated, and isn't the payload of an error packet, so we can checksum
1332 ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1334 if (computed_cksum == 0) {
1335 proto_tree_add_uint_format_value(icmp_tree,
1336 hf_icmp_checksum, tvb,
1341 proto_tree_add_boolean(icmp_tree,
1342 hf_icmp_checksum_bad,
1344 PROTO_ITEM_SET_HIDDEN(item);
1346 proto_tree_add_uint_format_value(icmp_tree,
1347 hf_icmp_checksum, tvb,
1349 "0x%04x [incorrect, should be 0x%04x]",
1351 in_cksum_shouldbe(cksum,
1354 proto_tree_add_boolean(icmp_tree,
1355 hf_icmp_checksum_bad,
1357 PROTO_ITEM_SET_HIDDEN(item);
1360 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1364 /* Decode the second 4 bytes of the packet. */
1365 switch (icmp_type) {
1366 case ICMP_ECHOREPLY:
1369 case ICMP_TSTAMPREPLY:
1371 case ICMP_IREQREPLY:
1373 case ICMP_MASKREPLY:
1374 proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2,
1376 proto_tree_add_item(icmp_tree, hf_icmp_ident_le, tvb, 4, 2,
1378 proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2,
1380 proto_tree_add_item(icmp_tree, hf_icmp_seq_num_le, tvb, 6,
1381 2, ENC_LITTLE_ENDIAN);
1382 col_append_fstr(pinfo->cinfo, COL_INFO,
1383 " id=0x%04x, seq=%u/%u, ttl=%u",
1384 tvb_get_ntohs(tvb, 4), tvb_get_ntohs(tvb,
1386 tvb_get_letohs(tvb, 6), (iph != NULL) ? iph->ip_ttl : 0);
1391 /* If icmp_original_dgram_length > 0, then this packet is compliant with RFC 4884 and
1392 * interpret the 6th octet as length of the original datagram
1394 if (icmp_original_dgram_length > 0) {
1395 ti = proto_tree_add_item(icmp_tree, hf_icmp_length,
1398 proto_item_append_text(ti,
1399 "Length of original datagram: %u",
1400 icmp_original_dgram_length *
1405 switch (icmp_code) {
1406 case ICMP_FRAG_NEEDED:
1407 proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6,
1413 case ICMP_RTRADVERT:
1414 num_addrs = tvb_get_guint8(tvb, 4);
1415 proto_tree_add_text(icmp_tree, tvb, 4, 1,
1416 "Number of addresses: %u", num_addrs);
1417 addr_entry_size = tvb_get_guint8(tvb, 5);
1418 proto_tree_add_text(icmp_tree, tvb, 5, 1,
1419 "Address entry size: %u",
1421 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1422 time_secs_to_str(wmem_packet_scope(), tvb_get_ntohs
1426 case ICMP_PARAMPROB:
1427 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1428 tvb_get_guint8(tvb, 4));
1429 if (icmp_original_dgram_length > 0) {
1430 ti = proto_tree_add_item(icmp_tree, hf_icmp_length,
1433 proto_item_append_text(ti,
1434 " Length of original datagram: %u",
1435 icmp_original_dgram_length *
1441 proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4,
1446 if (icmp_original_dgram_length > 0) {
1447 ti = proto_tree_add_item(icmp_tree, hf_icmp_length,
1450 proto_item_append_text(ti,
1451 " Length of original datagram: %u",
1452 icmp_original_dgram_length *
1457 /* Decode the additional information in the packet. */
1458 switch (icmp_type) {
1461 case ICMP_PARAMPROB:
1462 case ICMP_SOURCEQUENCH:
1464 /* Save the current value of the "we're inside an error packet"
1465 flag, and set that flag; subdissectors may treat packets
1466 that are the payload of error packets differently from
1468 save_in_error_pkt = pinfo->flags.in_error_pkt;
1469 pinfo->flags.in_error_pkt = TRUE;
1471 /* Decode the IP header and first 64 bits of data from the
1472 original datagram. */
1473 next_tvb = tvb_new_subset_remaining(tvb, 8);
1475 /* If the packet is compliant with RFC 4884, then it has
1476 * icmp_original_dgram_length*4 bytes of original IP packet that needs
1477 * to be decoded, followed by extension objects.
1479 if (icmp_original_dgram_length
1480 && (tvb_reported_length(tvb) >
1481 (guint) (8 + icmp_original_dgram_length * 4))
1482 && (tvb_get_ntohs(tvb, 8 + 2) >
1483 (guint) icmp_original_dgram_length * 4)) {
1484 set_actual_length(next_tvb,
1485 icmp_original_dgram_length * 4);
1487 /* There is a collision between RFC 1812 and draft-ietf-mpls-icmp-02.
1488 We don't know how to decode the 128th and following bytes of the ICMP payload.
1489 According to draft-ietf-mpls-icmp-02, these bytes should be decoded as MPLS extensios
1490 whereas RFC 1812 tells us to decode them as a portion of the original packet.
1491 Let the user decide.
1493 Here the user decided to favor MPLS extensions.
1494 Force the IP dissector to decode only the first 128 bytes. */
1495 if ((tvb_reported_length(tvb) > 8 + 128) &&
1497 && (tvb_get_ntohs(tvb, 8 + 2) > 128)) {
1498 set_actual_length(next_tvb, 128);
1502 call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1504 /* Restore the "we're inside an error packet" flag. */
1505 pinfo->flags.in_error_pkt = save_in_error_pkt;
1507 /* Decode MPLS extensions if the payload has at least 128 bytes, and
1508 - the original packet in the ICMP payload has less than 128 bytes, or
1509 - the user favors the MPLS extensions analysis */
1510 if ((tvb_reported_length(tvb) > 8 + 128)
1511 && (tvb_get_ntohs(tvb, 8 + 2) <= 128
1512 || favor_icmp_mpls_ext)) {
1513 dissect_extensions(tvb, 8 + 128, icmp_tree);
1516 case ICMP_ECHOREPLY:
1518 if (icmp_type == ICMP_ECHOREPLY) {
1519 if (!pinfo->flags.in_error_pkt) {
1521 (guint32) tvb_get_ntohs(tvb, 2);
1522 if (pinfo->flags.in_gre_pkt)
1523 conv_key[0] |= 0x00010000; /* set a bit for "in GRE" */
1525 (guint32) ((tvb_get_ntohs(tvb, 4) <<
1526 16) | tvb_get_ntohs(tvb,
1529 transaction_end(pinfo, icmp_tree,
1533 if (!pinfo->flags.in_error_pkt) {
1536 tmp[0] = ~tvb_get_ntohs(tvb, 2);
1537 tmp[1] = ~0x0800; /* The difference between echo request & reply */
1539 ip_checksum((guint8 *) & tmp,
1541 if (conv_key[0] == 0) {
1542 conv_key[0] = 0xffff;
1544 if (pinfo->flags.in_gre_pkt) {
1545 conv_key[0] |= 0x00010000; /* set a bit for "in GRE" */
1548 (guint32) ((tvb_get_ntohs(tvb, 4) <<
1549 16) | tvb_get_ntohs(tvb,
1552 transaction_start(pinfo, icmp_tree,
1557 /* Make sure we have enough bytes in the payload before trying to
1558 * see if the data looks like a timestamp; otherwise we'll get
1559 * malformed packets as we try to access data that isn't there. */
1560 if (tvb_length_remaining(tvb, 8) < 8) {
1561 if (tvb_length_remaining(tvb, 8) > 0) {
1562 call_dissector(data_handle,
1563 tvb_new_subset_remaining
1564 (tvb, 8), pinfo, icmp_tree);
1569 /* Interpret the first 8 bytes of the icmp data as a timestamp
1570 * But only if it does look like it's a timestamp.
1573 * Timestamps could be in different formats depending on the OS
1575 ts.secs = tvb_get_ntohl(tvb, 8);
1576 ts.nsecs = tvb_get_ntohl(tvb, 8 + 4); /* Leave at microsec resolution for now */
1577 if ((guint32) (ts.secs - pinfo->fd->abs_ts.secs) >=
1578 3600 * 24 || ts.nsecs >= 1000000) {
1579 /* Timestamp does not look right in BE, try LE representation */
1580 ts.secs = tvb_get_letohl(tvb, 8);
1581 ts.nsecs = tvb_get_letohl(tvb, 8 + 4); /* Leave at microsec resolution for now */
1583 if ((guint32) (ts.secs - pinfo->fd->abs_ts.secs) <
1584 3600 * 24 && ts.nsecs < 1000000) {
1585 ts.nsecs *= 1000; /* Convert to nanosec resolution */
1586 proto_tree_add_time(icmp_tree, hf_icmp_data_time,
1588 nstime_delta(&time_relative, &pinfo->fd->abs_ts,
1590 ti = proto_tree_add_time(icmp_tree,
1591 hf_icmp_data_time_relative,
1594 PROTO_ITEM_SET_GENERATED(ti);
1595 call_dissector(data_handle,
1596 tvb_new_subset_remaining(tvb,
1600 call_dissector(data_handle,
1601 tvb_new_subset_remaining(tvb, 8),
1606 case ICMP_RTRADVERT:
1607 if (addr_entry_size == 2) {
1608 for (i = 0; i < num_addrs; i++) {
1609 proto_tree_add_text(icmp_tree, tvb,
1611 "Router address: %s",
1616 proto_tree_add_text(icmp_tree, tvb,
1618 "Preference level: %d",
1624 if ((icmp_code == 0) || (icmp_code == 16)) {
1626 dissect_mip_extensions(tvb, 8 + i * 8,
1630 call_dissector(data_handle,
1631 tvb_new_subset_remaining(tvb, 8),
1637 case ICMP_TSTAMPREPLY:
1639 guint32 frame_ts, orig_ts;
1641 frame_ts = (guint32)(((pinfo->fd->abs_ts.secs * 1000) +
1642 (pinfo->fd->abs_ts.nsecs / 1000000)) %
1646 get_best_guess_mstimeofday(tvb, 8, frame_ts);
1647 proto_tree_add_text(icmp_tree, tvb, 8, 4,
1648 "Originate timestamp: %s after midnight UTC",
1649 time_msecs_to_str(wmem_packet_scope(), orig_ts));
1651 proto_tree_add_text(icmp_tree, tvb, 12, 4,
1652 "Receive timestamp: %s after midnight UTC",
1654 (wmem_packet_scope(), get_best_guess_mstimeofday
1655 (tvb, 12, orig_ts)));
1656 proto_tree_add_text(icmp_tree, tvb, 16, 4,
1657 "Transmit timestamp: %s after midnight UTC",
1659 (wmem_packet_scope(), get_best_guess_mstimeofday
1660 (tvb, 16, orig_ts)));
1665 case ICMP_MASKREPLY:
1666 proto_tree_add_text(icmp_tree, tvb, 8, 4,
1667 "Address mask: %s (0x%08x)",
1668 tvb_ip_to_str(tvb, 8),
1669 tvb_get_ntohl(tvb, 8));
1674 tap_queue_packet(icmp_tap, pinfo, trans);
1677 return tvb_length(tvb);
1680 void proto_register_icmp(void)
1682 static hf_register_info hf[] = {
1684 {"Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1688 {"Code", "icmp.code", FT_UINT8, BASE_DEC, NULL, 0x0,
1692 {"Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL,
1696 {&hf_icmp_checksum_bad,
1697 {"Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN,
1698 BASE_NONE, NULL, 0x0,
1702 {"Identifier (BE)", "icmp.ident", FT_UINT16, BASE_DEC_HEX,
1704 "Identifier (big endian representation)", HFILL}},
1707 {"Identifier (LE)", "icmp.ident", FT_UINT16, BASE_DEC_HEX,
1709 "Identifier (little endian representation)", HFILL}},
1712 {"Sequence number (BE)", "icmp.seq", FT_UINT16,
1713 BASE_DEC_HEX, NULL, 0x0,
1714 "Sequence number (big endian representation)", HFILL}},
1716 {&hf_icmp_seq_num_le,
1717 {"Sequence number (LE)", "icmp.seq_le", FT_UINT16,
1719 0x0, "Sequence number (little endian representation)",
1723 {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL,
1728 {"Gateway address", "icmp.redir_gw", FT_IPv4, BASE_NONE,
1733 {"Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
1734 VALS(mip_extensions), 0x0, NULL, HFILL}},
1736 {&hf_icmp_mip_length,
1737 {"Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL,
1741 {&hf_icmp_mip_prefix_length,
1742 {"Prefix Length", "icmp.mip.prefixlength", FT_UINT8,
1743 BASE_DEC, NULL, 0x0,
1747 {"Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC,
1752 {"Registration Lifetime", "icmp.mip.life", FT_UINT16,
1757 {&hf_icmp_mip_flags,
1758 {"Flags", "icmp.mip.flags", FT_UINT16, BASE_HEX, NULL,
1763 {"Registration Required", "icmp.mip.r", FT_BOOLEAN, 16,
1765 "Registration with this FA is required", HFILL}},
1768 {"Busy", "icmp.mip.b", FT_BOOLEAN, 16, NULL, 0x4000,
1769 "This FA will not accept requests at this time", HFILL}},
1772 {"Home Agent", "icmp.mip.h", FT_BOOLEAN, 16, NULL, 0x2000,
1773 "Home Agent Services Offered", HFILL}},
1776 {"Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 16, NULL,
1778 "Foreign Agent Services Offered", HFILL}},
1781 {"Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 16,
1783 "Minimal encapsulation tunneled datagram support",
1787 {"GRE", "icmp.mip.g", FT_BOOLEAN, 16, NULL, 0x0400,
1788 "GRE encapsulated tunneled datagram support", HFILL}},
1791 {"VJ Comp", "icmp.mip.v", FT_BOOLEAN, 16, NULL, 0x0200,
1792 "Van Jacobson Header Compression Support", HFILL}},
1795 {"Reverse tunneling", "icmp.mip.rt", FT_BOOLEAN, 16, NULL,
1797 "Reverse tunneling support", HFILL}},
1800 {"UDP tunneling", "icmp.mip.u", FT_BOOLEAN, 16, NULL,
1802 "UDP tunneling support", HFILL}},
1805 {"Revocation support", "icmp.mip.x", FT_BOOLEAN, 16, NULL,
1807 "Registration revocation support", HFILL}},
1809 {&hf_icmp_mip_reserved,
1810 {"Reserved", "icmp.mip.reserved", FT_UINT16, BASE_HEX,
1815 {"Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE,
1819 {&hf_icmp_mip_challenge,
1820 {"Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE,
1825 {"ICMP Extensions", "icmp.ext", FT_NONE, BASE_NONE, NULL,
1829 {&hf_icmp_ext_version,
1830 {"Version", "icmp.ext.version", FT_UINT8, BASE_DEC, NULL,
1834 {&hf_icmp_ext_reserved,
1835 {"Reserved", "icmp.ext.res", FT_UINT16, BASE_HEX, NULL,
1839 {&hf_icmp_ext_checksum,
1840 {"Checksum", "icmp.ext.checksum", FT_UINT16, BASE_HEX,
1844 {&hf_icmp_ext_checksum_bad,
1845 {"Bad Checksum", "icmp.ext.checksum_bad", FT_BOOLEAN,
1850 {&hf_icmp_ext_length,
1851 {"Length", "icmp.ext.length", FT_UINT16, BASE_DEC, NULL,
1855 {&hf_icmp_ext_class,
1856 {"Class", "icmp.ext.class", FT_UINT8, BASE_DEC, NULL, 0x0,
1859 {&hf_icmp_ext_c_type,
1860 {"C-Type", "icmp.ext.ctype", FT_UINT8, BASE_DEC, NULL,
1864 {&hf_icmp_mpls_label,
1865 {"Label", "icmp.mpls.label", FT_UINT24, BASE_DEC, NULL,
1870 {"Experimental", "icmp.mpls.exp", FT_UINT24, BASE_DEC,
1875 {"Stack bit", "icmp.mpls.s", FT_BOOLEAN, 24,
1876 TFS(&tfs_set_notset), 0x01,
1880 {"Time to live", "icmp.mpls.ttl", FT_UINT8, BASE_DEC,
1885 {"Response frame", "icmp.resp_in", FT_FRAMENUM, BASE_NONE,
1887 "The frame number of the corresponding response",
1891 {"No response seen", "icmp.no_resp", FT_NONE, BASE_NONE,
1893 "No corresponding response frame was seen",
1897 {"Request frame", "icmp.resp_to", FT_FRAMENUM, BASE_NONE,
1899 "The frame number of the corresponding request", HFILL}},
1902 {"Response time", "icmp.resptime", FT_DOUBLE, BASE_NONE,
1904 "The time between the request and the response, in ms.",
1907 {&hf_icmp_data_time,
1908 {"Timestamp from icmp data", "icmp.data_time",
1910 ABSOLUTE_TIME_LOCAL, NULL, 0x0,
1911 "The timestamp in the first 8 bytes of the icmp data",
1914 {&hf_icmp_data_time_relative,
1915 {"Timestamp from icmp data (relative)",
1916 "icmp.data_time_relative",
1917 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
1918 "The timestamp of the packet, relative to the timestamp in the first 8 bytes of the icmp data",
1922 {"Length of original datagram", "icmp.length", FT_UINT8,
1925 "The length of the original datagram", HFILL}},
1926 {&hf_icmp_int_info_role,
1927 {"Interface Role", "icmp.int_info.role",
1928 FT_UINT8, BASE_DEC, VALS(interface_role_str),
1929 INT_INFO_INTERFACE_ROLE,
1931 {&hf_icmp_int_info_reserved,
1932 {"Reserved", "icmp.int_info.reserved",
1933 FT_UINT8, BASE_DEC, NULL, INT_INFO_RESERVED,
1935 {&hf_icmp_int_info_ifindex,
1936 {"ifIndex", "icmp.int_info.ifindex", FT_BOOLEAN, 8, NULL,
1938 "True: ifIndex of the interface included; False: ifIndex of the interface not included ",
1940 {&hf_icmp_int_info_ipaddr,
1941 {"IP Address", "icmp.int_info.ipaddr", FT_BOOLEAN, 8,
1944 "True: IP Address Sub-Object present; False: IP Address Sub-Object not present",
1946 {&hf_icmp_int_info_name,
1947 {"Interface Name", "icmp.int_info.name", FT_BOOLEAN, 8,
1950 "True: Interface Name Sub-Object present; False: Interface Name Sub-Object not present",
1952 {&hf_icmp_int_info_mtu,
1953 {"MTU", "icmp.int_info.mtu", FT_BOOLEAN, 8, NULL,
1955 "True: MTU present; False: MTU not present", HFILL}},
1956 {&hf_icmp_int_info_afi,
1957 {"Address Family Identifier", "icmp.int_info.afi",
1958 FT_UINT16, BASE_DEC,
1960 "Address Family of the interface address", HFILL}},
1961 {&hf_icmp_int_info_ipv4,
1962 {"Source", "icmp.int_info.ipv4", FT_IPv4, BASE_NONE, NULL,
1965 {&hf_icmp_int_info_ipv6,
1966 {"Source", "icmp.int_info.ipv6", FT_IPv6, BASE_NONE, NULL,
1971 static gint *ett[] = {
1974 &ett_icmp_mip_flags,
1975 /* MPLS extensions */
1977 &ett_icmp_ext_object,
1978 &ett_icmp_mpls_stack_object,
1979 /* Interface Information Object RFC 5837 */
1980 &ett_icmp_interface_info_object,
1981 &ett_icmp_interface_ipaddr,
1982 &ett_icmp_interface_name
1985 static ei_register_info ei[] = {
1986 { &ei_icmp_resp_not_found, { "icmp.resp_not_found", PI_SEQUENCE, PI_WARN, "Response not found", EXPFILL }},
1989 module_t *icmp_module;
1990 expert_module_t* expert_icmp;
1993 proto_register_protocol("Internet Control Message Protocol",
1995 proto_register_field_array(proto_icmp, hf, array_length(hf));
1996 expert_icmp = expert_register_protocol(proto_icmp);
1997 expert_register_field_array(expert_icmp, ei, array_length(ei));
1998 proto_register_subtree_array(ett, array_length(ett));
2000 icmp_module = prefs_register_protocol(proto_icmp, NULL);
2002 prefs_register_bool_preference(icmp_module, "favor_icmp_mpls",
2003 "Favor ICMP extensions for MPLS",
2004 "Whether the 128th and following bytes of the ICMP payload should be decoded as MPLS extensions or as a portion of the original packet",
2005 &favor_icmp_mpls_ext);
2007 new_register_dissector("icmp", dissect_icmp, proto_icmp);
2008 icmp_tap = register_tap("icmp");
2011 void proto_reg_handoff_icmp(void)
2013 dissector_handle_t icmp_handle;
2016 * Get handle for the IP dissector.
2018 ip_handle = find_dissector("ip");
2019 icmp_handle = find_dissector("icmp");
2020 data_handle = find_dissector("data");
2022 dissector_add_uint("ip.proto", IP_PROTO_ICMP, icmp_handle);