MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-icmp.c
blobc7a05002c5a68b0c4030e0ff7c9aa18c44861542
1 /* packet-icmp.c
2 * Routines for ICMP - Internet Control Message Protocol
4 * $Id$
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * Monday, June 27, 2005
11 * Support for the ICMP extensions for MPLS
12 * (http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt
13 * which has been replaced by rfcs 4884 and 4950)
14 * by Maria-Luiza Crivat <luizacri@gmail.com>
15 * & Brice Augustin <bricecotte@gmail.com>
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 * Added support for ICMP extensions RFC 4884 and RFC 5837
32 * (c) 2011 Gaurav Tungatkar <gstungat@ncsu.edu>
35 #include "config.h"
37 #include <glib.h>
38 #include <time.h>
40 #include <epan/packet.h>
41 #include <epan/ipproto.h>
42 #include <epan/prefs.h>
43 #include <epan/in_cksum.h>
45 #include "packet-ip.h"
46 #include "packet-icmp.h"
47 #include <epan/conversation.h>
48 #include <epan/wmem/wmem.h>
49 #include <epan/tap.h>
51 static int icmp_tap = -1;
53 /* Conversation related data */
54 static int hf_icmp_resp_in = -1;
55 static int hf_icmp_resp_to = -1;
56 static int hf_icmp_resptime = -1;
57 static int hf_icmp_data_time = -1;
58 static int hf_icmp_data_time_relative = -1;
60 typedef struct _icmp_conv_info_t {
61 wmem_tree_t *unmatched_pdus;
62 wmem_tree_t *matched_pdus;
63 } icmp_conv_info_t;
65 static icmp_transaction_t *transaction_start(packet_info * pinfo,
66 proto_tree * tree,
67 guint32 * key);
68 static icmp_transaction_t *transaction_end(packet_info * pinfo,
69 proto_tree * tree,
70 guint32 * key);
72 /* Decode the end of the ICMP payload as ICMP MPLS extensions
73 if the packet in the payload has more than 128 bytes */
74 static gboolean favor_icmp_mpls_ext = FALSE;
76 int proto_icmp = -1;
77 static int hf_icmp_type = -1;
78 static int hf_icmp_code = -1;
79 static int hf_icmp_checksum = -1;
80 static int hf_icmp_checksum_bad = -1;
81 static int hf_icmp_ident = -1;
82 static int hf_icmp_ident_le = -1;
83 static int hf_icmp_seq_num = -1;
84 static int hf_icmp_seq_num_le = -1;
85 static int hf_icmp_mtu = -1;
86 static int hf_icmp_redir_gw = -1;
87 static int hf_icmp_length = -1;
89 /* Mobile ip */
90 static int hf_icmp_mip_type = -1;
91 static int hf_icmp_mip_length = -1;
92 static int hf_icmp_mip_prefix_length = -1;
93 static int hf_icmp_mip_seq = -1;
94 static int hf_icmp_mip_life = -1;
95 static int hf_icmp_mip_flags = -1;
96 static int hf_icmp_mip_r = -1;
97 static int hf_icmp_mip_b = -1;
98 static int hf_icmp_mip_h = -1;
99 static int hf_icmp_mip_f = -1;
100 static int hf_icmp_mip_m = -1;
101 static int hf_icmp_mip_g = -1;
102 static int hf_icmp_mip_v = -1;
103 static int hf_icmp_mip_rt = -1;
104 static int hf_icmp_mip_u = -1;
105 static int hf_icmp_mip_x = -1;
106 static int hf_icmp_mip_reserved = -1;
107 static int hf_icmp_mip_coa = -1;
108 static int hf_icmp_mip_challenge = -1;
110 /* extensions RFC 4884*/
111 static int hf_icmp_ext = -1;
112 static int hf_icmp_ext_version = -1;
113 static int hf_icmp_ext_reserved = -1;
114 static int hf_icmp_ext_checksum = -1;
115 static int hf_icmp_ext_checksum_bad = -1;
116 static int hf_icmp_ext_length = -1;
117 static int hf_icmp_ext_class = -1;
118 static int hf_icmp_ext_c_type = -1;
120 /* Interface information extension RFC 5837 */
121 static int hf_icmp_int_info_ifindex = -1;
122 static int hf_icmp_int_info_ipaddr = -1;
123 static int hf_icmp_int_info_name = -1;
124 static int hf_icmp_int_info_mtu = -1;
125 static int hf_icmp_int_info_afi = -1;
126 static int hf_icmp_int_info_ipv4 = -1;
127 static int hf_icmp_int_info_ipv6 = -1;
128 static int hf_icmp_int_info_role = -1;
129 static int hf_icmp_int_info_reserved = -1;
130 static gint ett_icmp_interface_info_object = -1;
131 static gint ett_icmp_interface_ipaddr = -1;
132 static gint ett_icmp_interface_name = -1;
133 /* MPLS extension object*/
134 static int hf_icmp_mpls_label = -1;
135 static int hf_icmp_mpls_exp = -1;
136 static int hf_icmp_mpls_s = -1;
137 static int hf_icmp_mpls_ttl = -1;
139 static gint ett_icmp = -1;
140 static gint ett_icmp_mip = -1;
141 static gint ett_icmp_mip_flags = -1;
143 /* extensions */
144 static gint ett_icmp_ext = -1;
145 static gint ett_icmp_ext_object = -1;
147 /* MPLS extensions */
148 static gint ett_icmp_mpls_stack_object = -1;
150 /* ICMP definitions */
151 #define ICMP_ECHOREPLY 0
152 #define ICMP_UNREACH 3
153 #define ICMP_SOURCEQUENCH 4
154 #define ICMP_REDIRECT 5
155 #define ICMP_ALTHOST 6
156 #define ICMP_ECHO 8
157 #define ICMP_RTRADVERT 9
158 #define ICMP_RTRSOLICIT 10
159 #define ICMP_TIMXCEED 11
160 #define ICMP_PARAMPROB 12
161 #define ICMP_TSTAMP 13
162 #define ICMP_TSTAMPREPLY 14
163 #define ICMP_IREQ 15
164 #define ICMP_IREQREPLY 16
165 #define ICMP_MASKREQ 17
166 #define ICMP_MASKREPLY 18
167 #define ICMP_PHOTURIS 40
169 /* ICMP UNREACHABLE */
170 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
171 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
172 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
173 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
174 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
175 #define ICMP_SR_FAILED 5 /* Source Route failed */
176 #define ICMP_NET_UNKNOWN 6
177 #define ICMP_HOST_UNKNOWN 7
178 #define ICMP_HOST_ISOLATED 8
179 #define ICMP_NET_ANO 9
180 #define ICMP_HOST_ANO 10
181 #define ICMP_NET_UNR_TOS 11
182 #define ICMP_HOST_UNR_TOS 12
183 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
184 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
185 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
187 #define ICMP_MIP_EXTENSION_PAD 0
188 #define ICMP_MIP_MOB_AGENT_ADV 16
189 #define ICMP_MIP_PREFIX_LENGTHS 19
190 #define ICMP_MIP_CHALLENGE 24
192 static dissector_handle_t ip_handle;
193 static dissector_handle_t data_handle;
195 static const value_string icmp_type_str[] = {
196 {ICMP_ECHOREPLY, "Echo (ping) reply"},
197 {1, "Reserved"},
198 {2, "Reserved"},
199 {ICMP_UNREACH, "Destination unreachable"},
200 {ICMP_SOURCEQUENCH, "Source quench (flow control)"},
201 {ICMP_REDIRECT, "Redirect"},
202 {ICMP_ALTHOST, "Alternate host address"},
203 {ICMP_ECHO, "Echo (ping) request"},
204 {ICMP_RTRADVERT, "Router advertisement"},
205 {ICMP_RTRSOLICIT, "Router solicitation"},
206 {ICMP_TIMXCEED, "Time-to-live exceeded"},
207 {ICMP_PARAMPROB, "Parameter problem"},
208 {ICMP_TSTAMP, "Timestamp request"},
209 {ICMP_TSTAMPREPLY, "Timestamp reply"},
210 {ICMP_IREQ, "Information request"},
211 {ICMP_IREQREPLY, "Information reply"},
212 {ICMP_MASKREQ, "Address mask request"},
213 {ICMP_MASKREPLY, "Address mask reply"},
214 {19, "Reserved (for security)"},
215 {30, "Traceroute"},
216 {31, "Datagram Conversion Error"},
217 {32, "Mobile Host Redirect"},
218 {33, "IPv6 Where-Are-You"},
219 {34, "IPv6 I-Am-Here"},
220 {35, "Mobile Registration Request"},
221 {36, "Mobile Registration Reply"},
222 {37, "Domain Name Request"},
223 {38, "Domain Name Reply"},
224 {39, "SKIP"},
225 {ICMP_PHOTURIS, "Photuris"},
226 {41, "Experimental mobility protocols"},
227 {0, NULL}
230 static const value_string unreach_code_str[] = {
231 {ICMP_NET_UNREACH, "Network unreachable"},
232 {ICMP_HOST_UNREACH, "Host unreachable"},
233 {ICMP_PROT_UNREACH, "Protocol unreachable"},
234 {ICMP_PORT_UNREACH, "Port unreachable"},
235 {ICMP_FRAG_NEEDED, "Fragmentation needed"},
236 {ICMP_SR_FAILED, "Source route failed"},
237 {ICMP_NET_UNKNOWN, "Destination network unknown"},
238 {ICMP_HOST_UNKNOWN, "Destination host unknown"},
239 {ICMP_HOST_ISOLATED, "Source host isolated"},
240 {ICMP_NET_ANO, "Network administratively prohibited"},
241 {ICMP_HOST_ANO, "Host administratively prohibited"},
242 {ICMP_NET_UNR_TOS, "Network unreachable for TOS"},
243 {ICMP_HOST_UNR_TOS, "Host unreachable for TOS"},
244 {ICMP_PKT_FILTERED, "Communication administratively filtered"},
245 {ICMP_PREC_VIOLATION, "Host precedence violation"},
246 {ICMP_PREC_CUTOFF, "Precedence cutoff in effect"},
247 {0, NULL}
250 static const value_string redir_code_str[] = {
251 {0, "Redirect for network"},
252 {1, "Redirect for host"},
253 {2, "Redirect for TOS and network"},
254 {3, "Redirect for TOS and host"},
255 {0, NULL}
258 static const value_string alt_host_code_str[] = {
259 {0, "Alternate address for host"},
260 {0, NULL}
263 static const value_string rtradvert_code_str[] = {
264 {0, "Normal router advertisement"},
265 {16, "Does not route common traffic"},
266 {0, NULL}
269 static const value_string ttl_code_str[] = {
270 {0, "Time to live exceeded in transit"},
271 {1, "Fragment reassembly time exceeded"},
272 {0, NULL}
275 static const value_string par_code_str[] = {
276 {0, "Pointer indicates the error"},
277 {1, "Required option missing"},
278 {2, "Bad length"},
279 {0, NULL}
282 static const value_string photuris_code_str[] = {
283 {0, "Bad SPI"},
284 {1, "Authentication Failed"},
285 {2, "Decompression Failed"},
286 {3, "Decryption Failed"},
287 {4, "Need Authentication"},
288 {5, "Need Authorization"},
289 {0, NULL}
292 static const value_string mip_extensions[] = {
293 {ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
294 {ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
295 /* RFC 2002 */
296 {ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
297 {ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
298 {0, NULL}
301 /* RFC 5837 ICMP extension - Interface Information Object
302 * Interface Role
304 static const value_string interface_role_str[] = {
305 {0, "IP interface upon which datagram arrived"},
307 "sub-IP component of an IP interface upon which datagram arrived"},
308 {2, "IP interface through which datagram would be forwarded"},
309 {3, "IP next-hop to which datagram would be forwarded"},
310 {0, NULL}
313 #define INT_INFO_INTERFACE_ROLE 0xc0
314 #define INT_INFO_RESERVED 0x30
315 #define INT_INFO_IFINDEX 0x08
316 #define INT_INFO_IPADDR 0x04
317 #define INT_INFO_NAME 0x02
318 #define INT_INFO_MTU 0x01
320 #define INTERFACE_INFORMATION_OBJECT_CLASS 2
322 #define MPLS_STACK_ENTRY_OBJECT_CLASS 1
323 #define MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS 0
325 #define MPLS_STACK_ENTRY_C_TYPE 1
326 #define MPLS_EXTENDED_PAYLOAD_C_TYPE 1
328 #define INET6_ADDRLEN 16
330 static conversation_t *_find_or_create_conversation(packet_info * pinfo)
332 conversation_t *conv = NULL;
334 /* Have we seen this conversation before? */
335 conv =
336 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
337 pinfo->ptype, 0, 0, 0);
338 if (conv == NULL) {
339 /* No, this is a new conversation. */
340 conv =
341 conversation_new(pinfo->fd->num, &pinfo->src,
342 &pinfo->dst, pinfo->ptype, 0, 0, 0);
344 return conv;
348 * Dissect the mobile ip advertisement extensions.
350 static void
351 dissect_mip_extensions(tvbuff_t * tvb, int offset, proto_tree * tree)
353 guint8 type;
354 guint8 length;
355 guint16 flags;
356 proto_item *ti;
357 proto_tree *mip_tree = NULL;
358 proto_tree *flags_tree = NULL;
359 gint numCOAs;
360 gint i;
362 /* Not much to do if we're not parsing everything */
363 if (!tree)
364 return;
366 while (tvb_reported_length_remaining(tvb, offset) > 0) {
367 type = tvb_get_guint8(tvb, offset + 0);
368 if (type) {
369 length = tvb_get_guint8(tvb, offset + 1);
370 } else {
371 length = 0;
374 ti = proto_tree_add_text(tree, tvb, offset,
375 type ? (length + 2) : 1,
376 "Ext: %s", val_to_str(type,
377 mip_extensions,
378 "Unknown ext %u"));
379 mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
381 switch (type) {
382 case ICMP_MIP_EXTENSION_PAD:
383 /* One byte padding extension */
384 /* Add our fields */
385 /* type */
386 proto_tree_add_item(mip_tree, hf_icmp_mip_type,
387 tvb, offset, 1,
388 ENC_BIG_ENDIAN);
389 offset++;
390 break;
391 case ICMP_MIP_MOB_AGENT_ADV:
392 /* Mobility Agent Advertisement Extension (RFC 2002) */
393 /* Add our fields */
394 /* type */
395 proto_tree_add_item(mip_tree, hf_icmp_mip_type,
396 tvb, offset, 1,
397 ENC_BIG_ENDIAN);
398 offset++;
399 /* length */
400 proto_tree_add_item(mip_tree, hf_icmp_mip_length,
401 tvb, offset, 1,
402 ENC_BIG_ENDIAN);
403 offset++;
404 /* sequence number */
405 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb,
406 offset, 2, ENC_BIG_ENDIAN);
407 offset += 2;
408 /* Registration Lifetime */
409 proto_tree_add_item(mip_tree, hf_icmp_mip_life,
410 tvb, offset, 2,
411 ENC_BIG_ENDIAN);
412 offset += 2;
413 /* flags */
414 flags = tvb_get_ntohs(tvb, offset);
415 ti = proto_tree_add_uint(mip_tree,
416 hf_icmp_mip_flags, tvb,
417 offset, 2, flags);
418 flags_tree =
419 proto_item_add_subtree(ti, ett_icmp_mip_flags);
420 proto_tree_add_boolean(flags_tree, hf_icmp_mip_r,
421 tvb, offset, 2, flags);
422 proto_tree_add_boolean(flags_tree, hf_icmp_mip_b,
423 tvb, offset, 2, flags);
424 proto_tree_add_boolean(flags_tree, hf_icmp_mip_h,
425 tvb, offset, 2, flags);
426 proto_tree_add_boolean(flags_tree, hf_icmp_mip_f,
427 tvb, offset, 2, flags);
428 proto_tree_add_boolean(flags_tree, hf_icmp_mip_m,
429 tvb, offset, 2, flags);
430 proto_tree_add_boolean(flags_tree, hf_icmp_mip_g,
431 tvb, offset, 2, flags);
432 proto_tree_add_boolean(flags_tree, hf_icmp_mip_v,
433 tvb, offset, 2, flags);
434 proto_tree_add_boolean(flags_tree, hf_icmp_mip_rt,
435 tvb, offset, 2, flags);
436 proto_tree_add_boolean(flags_tree, hf_icmp_mip_u,
437 tvb, offset, 2, flags);
438 proto_tree_add_boolean(flags_tree, hf_icmp_mip_x,
439 tvb, offset, 2, flags);
441 /* Reserved */
442 proto_tree_add_uint(flags_tree,
443 hf_icmp_mip_reserved, tvb,
444 offset, 2, flags);
445 offset += 2;
447 /* COAs */
448 numCOAs = (length - 6) / 4;
449 for (i = 0; i < numCOAs; i++) {
450 proto_tree_add_item(mip_tree,
451 hf_icmp_mip_coa, tvb,
452 offset, 4,
453 ENC_BIG_ENDIAN);
454 offset += 4;
456 break;
457 case ICMP_MIP_PREFIX_LENGTHS:
458 /* Prefix-Lengths Extension (RFC 2002) */
459 /* Add our fields */
460 /* type */
461 proto_tree_add_item(mip_tree, hf_icmp_mip_type,
462 tvb, offset, 1,
463 ENC_BIG_ENDIAN);
464 offset++;
465 /* length */
466 proto_tree_add_item(mip_tree, hf_icmp_mip_length,
467 tvb, offset, 1,
468 ENC_BIG_ENDIAN);
469 offset++;
471 /* prefix lengths */
472 for (i = 0; i < length; i++) {
473 proto_tree_add_item(mip_tree,
474 hf_icmp_mip_prefix_length,
475 tvb, offset, 1,
476 ENC_BIG_ENDIAN);
477 offset++;
479 break;
480 case ICMP_MIP_CHALLENGE:
481 /* Challenge Extension (RFC 3012) */
482 /* type */
483 proto_tree_add_item(mip_tree, hf_icmp_mip_type,
484 tvb, offset, 1,
485 ENC_BIG_ENDIAN);
486 offset++;
487 /* length */
488 proto_tree_add_item(mip_tree, hf_icmp_mip_length,
489 tvb, offset, 1,
490 ENC_BIG_ENDIAN);
491 offset++;
492 /* challenge */
493 proto_tree_add_item(mip_tree,
494 hf_icmp_mip_challenge, tvb,
495 offset, length, ENC_NA);
496 offset += length;
498 break;
499 default:
500 /* type */
501 proto_tree_add_item(mip_tree, hf_icmp_mip_type,
502 tvb, offset, 1,
503 ENC_BIG_ENDIAN);
504 offset++;
505 /* length */
506 proto_tree_add_item(mip_tree, hf_icmp_mip_length,
507 tvb, offset, 1,
508 ENC_BIG_ENDIAN);
509 offset++;
510 /* data, if any */
511 if (length != 0) {
512 proto_tree_add_text(mip_tree, tvb, offset,
513 length, "Contents");
514 offset += length;
517 break;
521 } /* dissect_mip_extensions */
523 static gboolean
524 dissect_mpls_extended_payload_object(tvbuff_t * tvb, gint offset,
525 proto_tree * ext_object_tree,
526 proto_item * tf_object)
529 guint16 obj_length, obj_trunc_length;
530 gboolean unknown_object;
531 guint8 c_type;
532 unknown_object = FALSE;
533 /* Object length */
534 obj_length = tvb_get_ntohs(tvb, offset);
536 obj_trunc_length =
537 MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
539 /* C-Type */
540 c_type = tvb_get_guint8(tvb, offset + 3);
541 proto_tree_add_uint(ext_object_tree, hf_icmp_ext_c_type, tvb,
542 offset + 3, 1, c_type);
544 /* skip the object header */
545 offset += 4;
547 switch (c_type) {
548 case MPLS_EXTENDED_PAYLOAD_C_TYPE:
549 proto_item_set_text(tf_object, "Extended Payload");
551 /* This object contains some portion of the original packet
552 that could not fit in the 128 bytes of the ICMP payload */
553 if (obj_trunc_length > 4) {
554 proto_tree_add_text(ext_object_tree, tvb,
555 offset, obj_trunc_length - 4,
556 "Data (%d bytes)",
557 obj_trunc_length - 4);
559 break;
560 default:
561 unknown_object = TRUE;
562 } /* end switch c_type */
563 return unknown_object;
566 static gboolean
567 dissect_mpls_stack_entry_object(tvbuff_t * tvb, gint offset,
568 proto_tree * ext_object_tree,
569 proto_item * tf_object)
572 proto_item *tf_entry;
573 proto_tree *mpls_stack_object_tree;
574 guint16 obj_length, obj_trunc_length;
575 gint obj_end_offset;
576 guint label;
577 guint8 ttl;
578 guint8 tmp;
579 gboolean unknown_object;
580 guint8 c_type;
581 unknown_object = FALSE;
582 /* Object length */
583 obj_length = tvb_get_ntohs(tvb, offset);
585 obj_trunc_length =
586 MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
587 obj_end_offset = offset + obj_trunc_length;
588 /* C-Type */
589 c_type = tvb_get_guint8(tvb, offset + 3);
590 proto_tree_add_uint(ext_object_tree, hf_icmp_ext_c_type, tvb,
591 offset + 3, 1, c_type);
593 /* skip the object header */
594 offset += 4;
596 switch (c_type) {
597 case MPLS_STACK_ENTRY_C_TYPE:
598 proto_item_set_text(tf_object, "MPLS Stack Entry");
599 /* For each entry */
600 while (offset + 4 <= obj_end_offset) {
601 if (tvb_reported_length_remaining(tvb, offset) < 4) {
602 /* Not enough room in the packet ! */
603 break;
605 /* Create a subtree for each entry (the text will be set later) */
606 tf_entry = proto_tree_add_text(ext_object_tree,
607 tvb, offset, 4,
608 " ");
609 mpls_stack_object_tree =
610 proto_item_add_subtree(tf_entry,
611 ett_icmp_mpls_stack_object);
613 /* Label */
614 label = (guint) tvb_get_ntohs(tvb, offset);
615 tmp = tvb_get_guint8(tvb, offset + 2);
616 label = (label << 4) + (tmp >> 4);
618 proto_tree_add_uint(mpls_stack_object_tree,
619 hf_icmp_mpls_label, tvb,
620 offset, 3, label << 4);
622 proto_item_set_text(tf_entry, "Label: %u", label);
624 /* Experimental field (also called "CoS") */
625 proto_tree_add_uint(mpls_stack_object_tree,
626 hf_icmp_mpls_exp, tvb,
627 offset + 2, 1, tmp);
629 proto_item_append_text(tf_entry, ", Exp: %u",
630 (tmp >> 1) & 0x07);
632 /* Stack bit */
633 proto_tree_add_boolean(mpls_stack_object_tree,
634 hf_icmp_mpls_s, tvb,
635 offset + 2, 1, tmp);
637 proto_item_append_text(tf_entry, ", S: %u",
638 tmp & 0x01);
640 /* TTL */
641 ttl = tvb_get_guint8(tvb, offset + 3);
643 proto_tree_add_item(mpls_stack_object_tree,
644 hf_icmp_mpls_ttl, tvb,
645 offset + 3, 1, ENC_BIG_ENDIAN);
647 proto_item_append_text(tf_entry, ", TTL: %u", ttl);
649 /* Skip the entry */
650 offset += 4;
653 if (offset < obj_end_offset) {
654 proto_tree_add_text(ext_object_tree, tvb, offset,
655 obj_end_offset - offset,
656 "%d junk bytes",
657 obj_end_offset - offset);
659 break;
661 default:
663 unknown_object = TRUE;
665 break;
666 } /* end switch c_type */
667 return unknown_object;
669 } /* end dissect_mpls_stack_entry_object */
671 /* Dissect Interface Information Object RFC 5837*/
672 static gboolean
673 dissect_interface_information_object(tvbuff_t * tvb, gint offset,
674 proto_tree * ext_object_tree,
675 proto_item * tf_object)
677 proto_item *ti;
678 proto_tree *int_name_object_tree = NULL;
679 proto_tree *int_ipaddr_object_tree;
680 guint16 obj_length, obj_trunc_length;
681 gint obj_end_offset;
682 guint8 c_type;
683 gboolean unknown_object;
684 guint8 if_index_flag;
685 guint8 ipaddr_flag;
686 guint8 name_flag;
687 guint32 if_index;
688 guint16 afi;
689 struct e_in6_addr ipaddr_v6;
690 guint8 int_name_length = 0;
692 unknown_object = FALSE;
693 /* Object length */
694 obj_length = tvb_get_ntohs(tvb, offset);
696 obj_trunc_length =
697 MIN(obj_length, tvb_reported_length_remaining(tvb, offset));
698 obj_end_offset = offset + obj_trunc_length;
700 /* C-Type */
701 c_type = tvb_get_guint8(tvb, offset + 3);
703 proto_item_set_text(tf_object, "Interface Information Object");
704 if (tvb_reported_length_remaining(tvb, offset) < 4) {
705 /* Not enough room in the packet ! return unknown_object = TRUE */
706 return TRUE;
709 if_index_flag = (c_type & INT_INFO_IFINDEX) >> 3;
710 ipaddr_flag = (c_type & INT_INFO_IPADDR) >> 2;
711 name_flag = (c_type & INT_INFO_NAME) >> 1;
714 static const gint *c_type_fields[] = {
715 &hf_icmp_int_info_role,
716 &hf_icmp_int_info_reserved,
717 &hf_icmp_int_info_ifindex,
718 &hf_icmp_int_info_ipaddr,
719 &hf_icmp_int_info_name,
720 &hf_icmp_int_info_mtu,
721 NULL
723 proto_tree_add_bitmask(ext_object_tree, tvb, offset + 3,
724 hf_icmp_ext_c_type,
725 ett_icmp_interface_info_object,
726 c_type_fields, ENC_BIG_ENDIAN);
729 /* skip header */
730 offset += 4;
732 /*if ifIndex is set, next 32 bits are ifIndex */
733 if (if_index_flag) {
734 if (obj_end_offset >= offset + 4) {
735 if_index = tvb_get_ntohl(tvb, offset);
736 proto_tree_add_text(ext_object_tree,
737 tvb, offset, 4,
738 "Interface Index: %u",
739 if_index);
740 offset += 4;
741 } else {
742 proto_tree_add_text(ext_object_tree,
743 tvb, offset, 4,
744 "Interface Index:(truncated)");
745 return FALSE;
749 /* IP Address Sub Object */
750 if (ipaddr_flag && (obj_end_offset >= offset + 2)) {
751 /* Address Family Identifier */
752 afi = tvb_get_ntohs(tvb, offset);
755 * if afi = 1, IPv4 address, 2 bytes afi, 2 bytes rsvd, 4 bytes IP addr
756 * if afi = 2, IPv6 address, 2 bytes afi, 2 bytes rsvd, 6 bytes IP addr
758 ti = proto_tree_add_text(ext_object_tree, tvb, offset,
759 afi == 1 ? 8 : 10,
760 "IP Address Sub-Object");
762 int_ipaddr_object_tree =
763 proto_item_add_subtree(ti, ett_icmp_interface_ipaddr);
765 proto_tree_add_uint(int_ipaddr_object_tree,
766 hf_icmp_int_info_afi, tvb, offset, 2,
767 afi);
769 /* skip reserved */
770 offset += 4;
771 if (afi == 1 && (obj_end_offset >= offset + 4)) {
772 proto_tree_add_ipv4(int_ipaddr_object_tree,
773 hf_icmp_int_info_ipv4, tvb,
774 offset, 4, tvb_get_ntohl(tvb,
775 offset));
776 offset += 4;
777 } else if (afi == 2
778 && (obj_end_offset >= offset + INET6_ADDRLEN)) {
779 tvb_get_ipv6(tvb, offset, &ipaddr_v6);
780 proto_tree_add_ipv6(int_ipaddr_object_tree,
781 hf_icmp_int_info_ipv6, tvb,
782 offset, INET6_ADDRLEN,
783 (guint8 *) & ipaddr_v6);
784 offset += INET6_ADDRLEN;
785 } else {
786 proto_tree_add_text(int_ipaddr_object_tree, tvb,
787 offset,
788 offset - obj_end_offset,
789 "Bad IP Address");
790 return FALSE;
794 /* Interface Name Sub Object */
795 if (name_flag) {
796 if (obj_end_offset >= offset + 1) {
797 int_name_length = tvb_get_guint8(tvb, offset);
798 ti = proto_tree_add_text(ext_object_tree, tvb,
799 offset, int_name_length,
800 "Interface Name Sub-Object");
802 int_name_object_tree =
803 proto_item_add_subtree(ti,
804 ett_icmp_interface_name);
805 proto_tree_add_text(int_name_object_tree, tvb,
806 offset, 1, "Length: %u",
807 int_name_length);
809 if (obj_end_offset >= offset + 1 + int_name_length) {
811 proto_tree_add_text(int_name_object_tree, tvb,
812 offset + 1, int_name_length,
813 "Interface Name: %s",
814 tvb_format_text(tvb, offset + 1, int_name_length));
819 return unknown_object;
821 } /*end dissect_interface_information_object */
823 static void
824 dissect_extensions(tvbuff_t * tvb, gint offset, proto_tree * tree)
826 guint8 version;
827 guint8 class_num;
828 guint8 c_type;
829 guint16 cksum, computed_cksum;
830 guint16 obj_length, obj_trunc_length;
831 proto_item *ti, *tf_object, *hidden_item;
832 proto_tree *ext_tree, *ext_object_tree;
833 gint obj_end_offset;
834 guint reported_length;
835 gboolean unknown_object;
836 guint8 int_info_obj_count;
838 if (!tree)
839 return;
841 ext_tree = NULL;
842 int_info_obj_count = 0;
844 reported_length = tvb_reported_length_remaining(tvb, offset);
846 if (reported_length < 4 /* Common header */ ) {
847 proto_tree_add_text(tree, tvb, offset,
848 reported_length,
849 "ICMP Multi-Part Extensions (truncated)");
850 return;
853 /* Add a tree for multi-part extensions RFC 4884 */
854 ti = proto_tree_add_none_format(tree, hf_icmp_ext, tvb,
855 offset, reported_length,
856 "ICMP Multi-Part Extensions");
858 ext_tree = proto_item_add_subtree(ti, ett_icmp_ext);
860 /* Version */
861 version = hi_nibble(tvb_get_guint8(tvb, offset));
862 proto_tree_add_uint(ext_tree, hf_icmp_ext_version, tvb, offset, 1,
863 version);
865 /* Reserved */
866 proto_tree_add_item(ext_tree, hf_icmp_ext_reserved,
867 tvb, offset, 2, ENC_BIG_ENDIAN);
869 /* Checksum */
870 cksum = tvb_get_ntohs(tvb, offset + 2);
872 computed_cksum =
873 ip_checksum(tvb_get_ptr(tvb, offset, reported_length),
874 reported_length);
876 if (computed_cksum == 0) {
877 proto_tree_add_uint_format_value(ext_tree, hf_icmp_ext_checksum,
878 tvb, offset + 2, 2, cksum,
879 "0x%04x [correct]",
880 cksum);
881 hidden_item =
882 proto_tree_add_boolean(ext_tree,
883 hf_icmp_ext_checksum_bad, tvb,
884 offset + 2, 2, FALSE);
885 } else {
886 proto_tree_add_uint_format_value(ext_tree, hf_icmp_ext_checksum,
887 tvb, offset + 2, 2, cksum,
888 "0x%04x [incorrect, should be 0x%04x]",
889 cksum, in_cksum_shouldbe(cksum,
890 computed_cksum));
891 hidden_item =
892 proto_tree_add_boolean(ext_tree,
893 hf_icmp_ext_checksum_bad, tvb,
894 offset + 2, 2, TRUE);
896 PROTO_ITEM_SET_HIDDEN(hidden_item);
898 if (version != 1 && version != 2) {
899 /* Unsupported version */
900 proto_item_append_text(ti, " (unsupported version)");
901 return;
904 /* Skip the common header */
905 offset += 4;
907 /* While there is enough room to read an object */
908 while (tvb_reported_length_remaining(tvb, offset) >=
909 4 /* Object header */ ) {
910 /* Object length */
911 obj_length = tvb_get_ntohs(tvb, offset);
913 obj_trunc_length =
914 MIN(obj_length,
915 tvb_reported_length_remaining(tvb, offset));
917 obj_end_offset = offset + obj_trunc_length;
919 /* Add a subtree for this object (the text will be reset later) */
920 tf_object = proto_tree_add_text(ext_tree, tvb, offset,
921 MAX(obj_trunc_length, 4),
922 "Unknown object");
924 ext_object_tree =
925 proto_item_add_subtree(tf_object, ett_icmp_ext_object);
927 proto_tree_add_uint(ext_object_tree, hf_icmp_ext_length,
928 tvb, offset, 2, obj_length);
930 /* Class */
931 class_num = tvb_get_guint8(tvb, offset + 2);
932 proto_tree_add_uint(ext_object_tree, hf_icmp_ext_class,
933 tvb, offset + 2, 1, class_num);
935 /* C-Type */
936 c_type = tvb_get_guint8(tvb, offset + 3);
938 if (obj_length < 4 /* Object header */ ) {
939 /* Thanks doc/README.developer :)) */
940 proto_item_set_text(tf_object,
941 "Object with bad length");
942 break;
946 switch (class_num) {
947 case MPLS_STACK_ENTRY_OBJECT_CLASS:
948 unknown_object =
949 dissect_mpls_stack_entry_object(tvb, offset,
950 ext_object_tree,
951 tf_object);
952 break;
953 case INTERFACE_INFORMATION_OBJECT_CLASS:
954 unknown_object =
955 dissect_interface_information_object(tvb,
956 offset,
957 ext_object_tree,
958 tf_object);
959 int_info_obj_count++;
960 if (int_info_obj_count > 4) {
961 proto_item_set_text(tf_object,
962 "More than 4 Interface Information Objects");
964 break;
965 case MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS:
966 unknown_object =
967 dissect_mpls_extended_payload_object(tvb,
968 offset,
969 ext_object_tree,
970 tf_object);
971 break;
972 default:
974 unknown_object = TRUE;
976 break;
977 } /* end switch class_num */
979 /* Skip the object header */
980 offset += 4;
982 /* The switches couldn't decode the object */
983 if (unknown_object == TRUE) {
984 proto_item_set_text(tf_object,
985 "Unknown object (%d/%d)",
986 class_num, c_type);
988 if (obj_trunc_length > 4) {
989 proto_tree_add_text(ext_object_tree, tvb,
990 offset,
991 obj_trunc_length - 4,
992 "Data (%d bytes)",
993 obj_trunc_length - 4);
997 /* */
998 if (obj_trunc_length < obj_length) {
999 proto_item_append_text(tf_object, " (truncated)");
1002 /* Go to the end of the object */
1003 offset = obj_end_offset;
1008 #include <stdio.h>
1009 /* ======================================================================= */
1010 static icmp_transaction_t *transaction_start(packet_info * pinfo,
1011 proto_tree * tree,
1012 guint32 * key)
1014 conversation_t *conversation;
1015 icmp_conv_info_t *icmp_info;
1016 icmp_transaction_t *icmp_trans;
1017 wmem_tree_key_t icmp_key[3];
1018 proto_item *it;
1020 /* Handle the conversation tracking */
1021 conversation = _find_or_create_conversation(pinfo);
1022 icmp_info = (icmp_conv_info_t *)conversation_get_proto_data(conversation, proto_icmp);
1023 if (icmp_info == NULL) {
1024 icmp_info = wmem_new(wmem_file_scope(), icmp_conv_info_t);
1025 icmp_info->unmatched_pdus = wmem_tree_new(wmem_file_scope());
1026 icmp_info->matched_pdus = wmem_tree_new(wmem_file_scope());
1027 conversation_add_proto_data(conversation, proto_icmp,
1028 icmp_info);
1031 if (!PINFO_FD_VISITED(pinfo)) {
1032 /* this is a new request, create a new transaction structure and map it to the
1033 unmatched table
1035 icmp_key[0].length = 2;
1036 icmp_key[0].key = key;
1037 icmp_key[1].length = 0;
1038 icmp_key[1].key = NULL;
1040 icmp_trans = wmem_new(wmem_file_scope(), icmp_transaction_t);
1041 icmp_trans->rqst_frame = PINFO_FD_NUM(pinfo);
1042 icmp_trans->resp_frame = 0;
1043 icmp_trans->rqst_time = pinfo->fd->abs_ts;
1044 nstime_set_zero(&icmp_trans->resp_time);
1045 wmem_tree_insert32_array(icmp_info->unmatched_pdus, icmp_key,
1046 (void *) icmp_trans);
1047 } else {
1048 /* Already visited this frame */
1049 guint32 frame_num = pinfo->fd->num;
1051 icmp_key[0].length = 2;
1052 icmp_key[0].key = key;
1053 icmp_key[1].length = 1;
1054 icmp_key[1].key = &frame_num;
1055 icmp_key[2].length = 0;
1056 icmp_key[2].key = NULL;
1058 icmp_trans =
1059 (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->matched_pdus,
1060 icmp_key);
1062 if (icmp_trans == NULL) {
1063 return NULL;
1066 /* Print state tracking in the tree */
1067 if (icmp_trans->resp_frame) {
1068 it = proto_tree_add_uint(tree, hf_icmp_resp_in, NULL, 0, 0,
1069 icmp_trans->resp_frame);
1070 PROTO_ITEM_SET_GENERATED(it);
1072 col_append_fstr(pinfo->cinfo, COL_INFO, " (reply in %d)",
1073 icmp_trans->resp_frame);
1076 return icmp_trans;
1078 } /* transaction_start() */
1080 /* ======================================================================= */
1081 static icmp_transaction_t *transaction_end(packet_info * pinfo,
1082 proto_tree * tree,
1083 guint32 * key)
1085 conversation_t *conversation;
1086 icmp_conv_info_t *icmp_info;
1087 icmp_transaction_t *icmp_trans;
1088 wmem_tree_key_t icmp_key[3];
1089 proto_item *it;
1090 nstime_t ns;
1091 double resp_time;
1093 conversation =
1094 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1095 pinfo->ptype, 0, 0, 0);
1096 if (conversation == NULL) {
1097 return NULL;
1100 icmp_info = (icmp_conv_info_t *)conversation_get_proto_data(conversation, proto_icmp);
1101 if (icmp_info == NULL) {
1102 return NULL;
1105 if (!PINFO_FD_VISITED(pinfo)) {
1106 guint32 frame_num;
1108 icmp_key[0].length = 2;
1109 icmp_key[0].key = key;
1110 icmp_key[1].length = 0;
1111 icmp_key[1].key = NULL;
1112 icmp_trans =
1113 (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->unmatched_pdus,
1114 icmp_key);
1115 if (icmp_trans == NULL) {
1116 return NULL;
1119 /* we have already seen this response, or an identical one */
1120 if (icmp_trans->resp_frame != 0) {
1121 return NULL;
1124 icmp_trans->resp_frame = PINFO_FD_NUM(pinfo);
1126 /* we found a match. Add entries to the matched table for both request and reply frames
1128 icmp_key[0].length = 2;
1129 icmp_key[0].key = key;
1130 icmp_key[1].length = 1;
1131 icmp_key[1].key = &frame_num;
1132 icmp_key[2].length = 0;
1133 icmp_key[2].key = NULL;
1135 frame_num = icmp_trans->rqst_frame;
1136 wmem_tree_insert32_array(icmp_info->matched_pdus, icmp_key,
1137 (void *) icmp_trans);
1139 frame_num = icmp_trans->resp_frame;
1140 wmem_tree_insert32_array(icmp_info->matched_pdus, icmp_key,
1141 (void *) icmp_trans);
1142 } else {
1143 /* Already visited this frame */
1144 guint32 frame_num = pinfo->fd->num;
1146 icmp_key[0].length = 2;
1147 icmp_key[0].key = key;
1148 icmp_key[1].length = 1;
1149 icmp_key[1].key = &frame_num;
1150 icmp_key[2].length = 0;
1151 icmp_key[2].key = NULL;
1153 icmp_trans =
1154 (icmp_transaction_t *)wmem_tree_lookup32_array(icmp_info->matched_pdus,
1155 icmp_key);
1157 if (icmp_trans == NULL) {
1158 return NULL;
1163 it = proto_tree_add_uint(tree, hf_icmp_resp_to, NULL, 0, 0,
1164 icmp_trans->rqst_frame);
1165 PROTO_ITEM_SET_GENERATED(it);
1167 nstime_delta(&ns, &pinfo->fd->abs_ts, &icmp_trans->rqst_time);
1168 icmp_trans->resp_time = ns;
1169 resp_time = nstime_to_msec(&ns);
1170 it = proto_tree_add_double_format_value(tree, hf_icmp_resptime,
1171 NULL, 0, 0, resp_time,
1172 "%.3f ms", resp_time);
1173 PROTO_ITEM_SET_GENERATED(it);
1175 col_append_fstr(pinfo->cinfo, COL_INFO, " (request in %d)",
1176 icmp_trans->rqst_frame);
1178 return icmp_trans;
1180 } /* transaction_end() */
1182 #define MSPERDAY 86400000
1184 /* ======================================================================= */
1185 static guint32
1186 get_best_guess_mstimeofday(tvbuff_t * tvb, gint offset, guint32 comp_ts)
1188 guint32 be_ts, le_ts;
1190 /* Account for the special case from RFC 792 as best we can by clearing
1191 * the msb. Ref: [Page 16] of http://tools.ietf.org/html/rfc792:
1193 If the time is not available in milliseconds or cannot be provided
1194 with respect to midnight UT then any time can be inserted in a
1195 timestamp provided the high order bit of the timestamp is also set
1196 to indicate this non-standard value.
1198 be_ts = tvb_get_ntohl(tvb, offset) & 0x7fffffff;
1199 le_ts = tvb_get_letohl(tvb, offset) & 0x7fffffff;
1201 if (be_ts < MSPERDAY && le_ts >= MSPERDAY) {
1202 return be_ts;
1205 if (le_ts < MSPERDAY && be_ts >= MSPERDAY) {
1206 return le_ts;
1209 if (be_ts < MSPERDAY && le_ts < MSPERDAY) {
1210 guint32 saved_be_ts = be_ts;
1211 guint32 saved_le_ts = le_ts;
1213 /* Is this a rollover to a new day, clocks not synchronized, different
1214 * timezones between originate and receive/transmit, .. what??? */
1215 if (be_ts < comp_ts && be_ts <= (MSPERDAY / 4)
1216 && comp_ts >= (MSPERDAY - (MSPERDAY / 4)))
1217 be_ts += MSPERDAY; /* Assume a rollover to a new day */
1218 if (le_ts < comp_ts && le_ts <= (MSPERDAY / 4)
1219 && comp_ts >= (MSPERDAY - (MSPERDAY / 4)))
1220 le_ts += MSPERDAY; /* Assume a rollover to a new day */
1221 if (abs(be_ts - comp_ts) < abs(le_ts - comp_ts))
1222 return saved_be_ts;
1223 return saved_le_ts;
1226 /* Both are bigger than MSPERDAY, but neither one's msb's are set. This
1227 * is clearly invalid, but now what TODO? For now, take the one closest to
1228 * the comparative timestamp, which is another way of saying, "let's
1229 * return a deterministic wild guess. */
1230 if (abs(be_ts - comp_ts) < abs(le_ts - comp_ts)) {
1231 return be_ts;
1233 return le_ts;
1234 } /* get_best_guess_mstimeofday() */
1237 * RFC 792 for basic ICMP.
1238 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1239 * RFC 1256 for router discovery messages.
1240 * RFC 2002 and 3012 for Mobile IP stuff.
1242 static void
1243 dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1245 proto_tree *icmp_tree = NULL;
1246 proto_item *ti;
1247 guint8 icmp_type;
1248 guint8 icmp_code;
1249 guint8 icmp_original_dgram_length;
1250 guint length, reported_length;
1251 guint16 cksum, computed_cksum;
1252 const gchar *type_str, *code_str;
1253 guint8 num_addrs = 0;
1254 guint8 addr_entry_size = 0;
1255 int i;
1256 gboolean save_in_error_pkt;
1257 tvbuff_t *next_tvb;
1258 proto_item *item;
1259 guint32 conv_key[2];
1260 icmp_transaction_t *trans = NULL;
1261 nstime_t ts, time_relative;
1263 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1264 col_clear(pinfo->cinfo, COL_INFO);
1266 /* To do: check for runts, errs, etc. */
1267 icmp_type = tvb_get_guint8(tvb, 0);
1268 icmp_code = tvb_get_guint8(tvb, 1);
1269 cksum = tvb_get_ntohs(tvb, 2);
1270 /*length of original datagram carried in the ICMP payload. In terms of 32 bit
1271 * words.*/
1272 icmp_original_dgram_length = tvb_get_guint8(tvb, 5);
1274 type_str =
1275 val_to_str_const(icmp_type, icmp_type_str,
1276 "Unknown ICMP (obsolete or malformed?)");
1278 switch (icmp_type) {
1279 case ICMP_UNREACH:
1280 code_str =
1281 val_to_str(icmp_code, unreach_code_str,
1282 "Unknown code: %u");
1283 break;
1284 case ICMP_REDIRECT:
1285 code_str =
1286 val_to_str(icmp_code, redir_code_str,
1287 "Unknown code: %u");
1288 break;
1289 case ICMP_ALTHOST:
1290 code_str =
1291 val_to_str(icmp_code, alt_host_code_str,
1292 "Unknown code: %u");
1293 break;
1294 case ICMP_RTRADVERT:
1295 switch (icmp_code) {
1296 case 0: /* Mobile-Ip */
1297 case 16: /* Mobile-Ip */
1298 type_str = "Mobile IP Advertisement";
1299 break;
1300 } /* switch icmp_code */
1301 code_str =
1302 val_to_str(icmp_code, rtradvert_code_str,
1303 "Unknown code: %u");
1304 break;
1305 case ICMP_TIMXCEED:
1306 code_str =
1307 val_to_str(icmp_code, ttl_code_str,
1308 "Unknown code: %u");
1309 break;
1310 case ICMP_PARAMPROB:
1311 code_str =
1312 val_to_str(icmp_code, par_code_str,
1313 "Unknown code: %u");
1314 break;
1315 case ICMP_PHOTURIS:
1316 code_str =
1317 val_to_str(icmp_code, photuris_code_str,
1318 "Unknown code: %u");
1319 break;
1320 default:
1321 code_str = NULL;
1322 break;
1325 col_add_fstr(pinfo->cinfo, COL_INFO, "%-20s", type_str);
1326 if (code_str) {
1327 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", code_str);
1330 length = tvb_length(tvb);
1331 reported_length = tvb_reported_length(tvb);
1333 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, ENC_NA);
1334 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1336 ti = proto_tree_add_item(icmp_tree, hf_icmp_type, tvb, 0, 1,
1337 ENC_BIG_ENDIAN);
1338 proto_item_append_text(ti, " (%s)", type_str);
1340 ti = proto_tree_add_item(icmp_tree, hf_icmp_code, tvb, 1, 1,
1341 ENC_BIG_ENDIAN);
1342 if (code_str) {
1343 proto_item_append_text(ti, " (%s)", code_str);
1346 if (!pinfo->fragmented && length >= reported_length
1347 && !pinfo->flags.in_error_pkt) {
1348 /* The packet isn't part of a fragmented datagram, isn't
1349 truncated, and isn't the payload of an error packet, so we can checksum
1350 it. */
1352 computed_cksum =
1353 ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1354 reported_length);
1355 if (computed_cksum == 0) {
1356 proto_tree_add_uint_format_value(icmp_tree,
1357 hf_icmp_checksum, tvb,
1358 2, 2, cksum,
1359 "0x%04x [correct]",
1360 cksum);
1361 item =
1362 proto_tree_add_boolean(icmp_tree,
1363 hf_icmp_checksum_bad,
1364 tvb, 2, 2, FALSE);
1365 PROTO_ITEM_SET_HIDDEN(item);
1366 } else {
1367 proto_tree_add_uint_format_value(icmp_tree,
1368 hf_icmp_checksum, tvb,
1369 2, 2, cksum,
1370 "0x%04x [incorrect, should be 0x%04x]",
1371 cksum,
1372 in_cksum_shouldbe(cksum,
1373 computed_cksum));
1374 item =
1375 proto_tree_add_boolean(icmp_tree,
1376 hf_icmp_checksum_bad,
1377 tvb, 2, 2, TRUE);
1378 PROTO_ITEM_SET_HIDDEN(item);
1380 } else {
1381 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1382 cksum);
1385 /* Decode the second 4 bytes of the packet. */
1386 switch (icmp_type) {
1387 case ICMP_ECHOREPLY:
1388 case ICMP_ECHO:
1389 case ICMP_TSTAMP:
1390 case ICMP_TSTAMPREPLY:
1391 case ICMP_IREQ:
1392 case ICMP_IREQREPLY:
1393 case ICMP_MASKREQ:
1394 case ICMP_MASKREPLY:
1395 proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2,
1396 ENC_BIG_ENDIAN);
1397 proto_tree_add_item(icmp_tree, hf_icmp_ident_le, tvb, 4, 2,
1398 ENC_LITTLE_ENDIAN);
1399 proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2,
1400 ENC_BIG_ENDIAN);
1401 proto_tree_add_item(icmp_tree, hf_icmp_seq_num_le, tvb, 6,
1402 2, ENC_LITTLE_ENDIAN);
1403 col_append_fstr(pinfo->cinfo, COL_INFO,
1404 " id=0x%04x, seq=%u/%u, ttl=%u",
1405 tvb_get_ntohs(tvb, 4), tvb_get_ntohs(tvb,
1407 tvb_get_letohs(tvb, 6), pinfo->ip_ttl);
1408 break;
1410 case ICMP_UNREACH:
1412 /* If icmp_original_dgram_length > 0, then this packet is compliant with RFC 4884 and
1413 * interpret the 6th octet as length of the original datagram
1415 if (icmp_original_dgram_length > 0) {
1416 ti = proto_tree_add_item(icmp_tree, hf_icmp_length,
1417 tvb, 5, 1,
1418 ENC_BIG_ENDIAN);
1419 proto_item_append_text(ti,
1420 "Length of original datagram: %u",
1421 icmp_original_dgram_length *
1426 switch (icmp_code) {
1427 case ICMP_FRAG_NEEDED:
1428 proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6,
1429 2, ENC_BIG_ENDIAN);
1430 break;
1432 break;
1434 case ICMP_RTRADVERT:
1435 num_addrs = tvb_get_guint8(tvb, 4);
1436 proto_tree_add_text(icmp_tree, tvb, 4, 1,
1437 "Number of addresses: %u", num_addrs);
1438 addr_entry_size = tvb_get_guint8(tvb, 5);
1439 proto_tree_add_text(icmp_tree, tvb, 5, 1,
1440 "Address entry size: %u",
1441 addr_entry_size);
1442 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1443 time_secs_to_str(tvb_get_ntohs
1444 (tvb, 6)));
1445 break;
1447 case ICMP_PARAMPROB:
1448 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1449 tvb_get_guint8(tvb, 4));
1450 if (icmp_original_dgram_length > 0) {
1451 ti = proto_tree_add_item(icmp_tree, hf_icmp_length,
1452 tvb, 5, 1,
1453 ENC_BIG_ENDIAN);
1454 proto_item_append_text(ti,
1455 " Length of original datagram: %u",
1456 icmp_original_dgram_length *
1459 break;
1461 case ICMP_REDIRECT:
1462 proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4,
1463 ENC_BIG_ENDIAN);
1464 break;
1466 case ICMP_TIMXCEED:
1467 if (icmp_original_dgram_length > 0) {
1468 ti = proto_tree_add_item(icmp_tree, hf_icmp_length,
1469 tvb, 5, 1,
1470 ENC_BIG_ENDIAN);
1471 proto_item_append_text(ti,
1472 " Length of original datagram: %u",
1473 icmp_original_dgram_length *
1478 /* Decode the additional information in the packet. */
1479 switch (icmp_type) {
1480 case ICMP_UNREACH:
1481 case ICMP_TIMXCEED:
1482 case ICMP_PARAMPROB:
1483 case ICMP_SOURCEQUENCH:
1484 case ICMP_REDIRECT:
1485 /* Save the current value of the "we're inside an error packet"
1486 flag, and set that flag; subdissectors may treat packets
1487 that are the payload of error packets differently from
1488 "real" packets. */
1489 save_in_error_pkt = pinfo->flags.in_error_pkt;
1490 pinfo->flags.in_error_pkt = TRUE;
1492 /* Decode the IP header and first 64 bits of data from the
1493 original datagram. */
1494 next_tvb = tvb_new_subset_remaining(tvb, 8);
1496 /* If the packet is compliant with RFC 4884, then it has
1497 * icmp_original_dgram_length*4 bytes of original IP packet that needs
1498 * to be decoded, followed by extension objects.
1500 if (icmp_original_dgram_length
1501 && (tvb_reported_length(tvb) >
1502 (guint) (8 + icmp_original_dgram_length * 4))
1503 && (tvb_get_ntohs(tvb, 8 + 2) >
1504 (guint) icmp_original_dgram_length * 4)) {
1505 set_actual_length(next_tvb,
1506 icmp_original_dgram_length * 4);
1507 } else {
1508 /* There is a collision between RFC 1812 and draft-ietf-mpls-icmp-02.
1509 We don't know how to decode the 128th and following bytes of the ICMP payload.
1510 According to draft-ietf-mpls-icmp-02, these bytes should be decoded as MPLS extensios
1511 whereas RFC 1812 tells us to decode them as a portion of the original packet.
1512 Let the user decide.
1514 Here the user decided to favor MPLS extensions.
1515 Force the IP dissector to decode only the first 128 bytes. */
1516 if ((tvb_reported_length(tvb) > 8 + 128) &&
1517 favor_icmp_mpls_ext
1518 && (tvb_get_ntohs(tvb, 8 + 2) > 128)) {
1519 set_actual_length(next_tvb, 128);
1523 call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1525 /* Restore the "we're inside an error packet" flag. */
1526 pinfo->flags.in_error_pkt = save_in_error_pkt;
1528 /* Decode MPLS extensions if the payload has at least 128 bytes, and
1529 - the original packet in the ICMP payload has less than 128 bytes, or
1530 - the user favors the MPLS extensions analysis */
1531 if ((tvb_reported_length(tvb) > 8 + 128)
1532 && (tvb_get_ntohs(tvb, 8 + 2) <= 128
1533 || favor_icmp_mpls_ext)) {
1534 dissect_extensions(tvb, 8 + 128, icmp_tree);
1536 break;
1537 case ICMP_ECHOREPLY:
1538 case ICMP_ECHO:
1539 if (icmp_type == ICMP_ECHOREPLY) {
1540 if (!pinfo->flags.in_error_pkt) {
1541 conv_key[0] =
1542 (guint32) tvb_get_ntohs(tvb, 2);
1543 if (pinfo->flags.in_gre_pkt)
1544 conv_key[0] |= 0x00010000; /* set a bit for "in GRE" */
1545 conv_key[1] =
1546 (guint32) ((tvb_get_ntohs(tvb, 4) <<
1547 16) | tvb_get_ntohs(tvb,
1548 6));
1549 trans =
1550 transaction_end(pinfo, icmp_tree,
1551 conv_key);
1553 } else {
1554 if (!pinfo->flags.in_error_pkt) {
1555 guint16 tmp[2];
1557 tmp[0] = ~tvb_get_ntohs(tvb, 2);
1558 tmp[1] = ~0x0800; /* The difference between echo request & reply */
1559 conv_key[0] =
1560 ip_checksum((guint8 *) & tmp,
1561 sizeof(tmp));
1562 if (conv_key[0] == 0) {
1563 conv_key[0] = 0xffff;
1565 if (pinfo->flags.in_gre_pkt) {
1566 conv_key[0] |= 0x00010000; /* set a bit for "in GRE" */
1568 conv_key[1] =
1569 (guint32) ((tvb_get_ntohs(tvb, 4) <<
1570 16) | tvb_get_ntohs(tvb,
1571 6));
1572 trans =
1573 transaction_start(pinfo, icmp_tree,
1574 conv_key);
1578 /* Make sure we have enough bytes in the payload before trying to
1579 * see if the data looks like a timestamp; otherwise we'll get
1580 * malformed packets as we try to access data that isn't there. */
1581 if (tvb_length_remaining(tvb, 8) < 8) {
1582 if (tvb_length_remaining(tvb, 8) > 0) {
1583 call_dissector(data_handle,
1584 tvb_new_subset_remaining
1585 (tvb, 8), pinfo, icmp_tree);
1587 break;
1590 /* Interpret the first 8 bytes of the icmp data as a timestamp
1591 * But only if it does look like it's a timestamp.
1593 * FIXME:
1594 * Timestamps could be in different formats depending on the OS
1596 ts.secs = tvb_get_ntohl(tvb, 8);
1597 ts.nsecs = tvb_get_ntohl(tvb, 8 + 4); /* Leave at microsec resolution for now */
1598 if (abs((guint32) (ts.secs - pinfo->fd->abs_ts.secs)) >=
1599 3600 * 24 || ts.nsecs >= 1000000) {
1600 /* Timestamp does not look right in BE, try LE representation */
1601 ts.secs = tvb_get_letohl(tvb, 8);
1602 ts.nsecs = tvb_get_letohl(tvb, 8 + 4); /* Leave at microsec resolution for now */
1604 if (abs((guint32) (ts.secs - pinfo->fd->abs_ts.secs)) <
1605 3600 * 24 && ts.nsecs < 1000000) {
1606 ts.nsecs *= 1000; /* Convert to nanosec resolution */
1607 proto_tree_add_time(icmp_tree, hf_icmp_data_time,
1608 tvb, 8, 8, &ts);
1609 nstime_delta(&time_relative, &pinfo->fd->abs_ts,
1610 &ts);
1611 ti = proto_tree_add_time(icmp_tree,
1612 hf_icmp_data_time_relative,
1613 tvb, 8, 8,
1614 &time_relative);
1615 PROTO_ITEM_SET_GENERATED(ti);
1616 call_dissector(data_handle,
1617 tvb_new_subset_remaining(tvb,
1618 8 + 8),
1619 pinfo, icmp_tree);
1620 } else {
1621 call_dissector(data_handle,
1622 tvb_new_subset_remaining(tvb, 8),
1623 pinfo, icmp_tree);
1625 break;
1627 case ICMP_RTRADVERT:
1628 if (addr_entry_size == 2) {
1629 for (i = 0; i < num_addrs; i++) {
1630 proto_tree_add_text(icmp_tree, tvb,
1631 8 + (i * 8), 4,
1632 "Router address: %s",
1633 tvb_ip_to_str(tvb,
1635 (i *
1636 8)));
1637 proto_tree_add_text(icmp_tree, tvb,
1638 12 + (i * 8), 4,
1639 "Preference level: %d",
1640 tvb_get_ntohl(tvb,
1641 12 +
1642 (i *
1643 8)));
1645 if ((icmp_code == 0) || (icmp_code == 16)) {
1646 /* Mobile-Ip */
1647 dissect_mip_extensions(tvb, 8 + i * 8,
1648 icmp_tree);
1650 } else {
1651 call_dissector(data_handle,
1652 tvb_new_subset_remaining(tvb, 8),
1653 pinfo, icmp_tree);
1655 break;
1657 case ICMP_TSTAMP:
1658 case ICMP_TSTAMPREPLY:
1660 guint32 frame_ts, orig_ts;
1662 frame_ts = (guint32)(((pinfo->fd->abs_ts.secs * 1000) +
1663 (pinfo->fd->abs_ts.nsecs / 1000000)) %
1664 86400000);
1666 orig_ts =
1667 get_best_guess_mstimeofday(tvb, 8, frame_ts);
1668 proto_tree_add_text(icmp_tree, tvb, 8, 4,
1669 "Originate timestamp: %s after midnight UTC",
1670 time_msecs_to_str(orig_ts));
1672 proto_tree_add_text(icmp_tree, tvb, 12, 4,
1673 "Receive timestamp: %s after midnight UTC",
1674 time_msecs_to_str
1675 (get_best_guess_mstimeofday
1676 (tvb, 12, orig_ts)));
1677 proto_tree_add_text(icmp_tree, tvb, 16, 4,
1678 "Transmit timestamp: %s after midnight UTC",
1679 time_msecs_to_str
1680 (get_best_guess_mstimeofday
1681 (tvb, 16, orig_ts)));
1683 break;
1685 case ICMP_MASKREQ:
1686 case ICMP_MASKREPLY:
1687 proto_tree_add_text(icmp_tree, tvb, 8, 4,
1688 "Address mask: %s (0x%08x)",
1689 tvb_ip_to_str(tvb, 8),
1690 tvb_get_ntohl(tvb, 8));
1691 break;
1694 if (trans) {
1695 tap_queue_packet(icmp_tap, pinfo, trans);
1699 void proto_register_icmp(void)
1701 static hf_register_info hf[] = {
1702 {&hf_icmp_type,
1703 {"Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1704 NULL, HFILL}},
1706 {&hf_icmp_code,
1707 {"Code", "icmp.code", FT_UINT8, BASE_DEC, NULL, 0x0,
1708 NULL, HFILL}},
1710 {&hf_icmp_checksum,
1711 {"Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL,
1712 0x0,
1713 NULL, HFILL}},
1715 {&hf_icmp_checksum_bad,
1716 {"Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN,
1717 BASE_NONE, NULL, 0x0,
1718 NULL, HFILL}},
1720 {&hf_icmp_ident,
1721 {"Identifier (BE)", "icmp.ident", FT_UINT16, BASE_DEC_HEX,
1722 NULL, 0x0,
1723 "Identifier (big endian representation)", HFILL}},
1725 {&hf_icmp_ident_le,
1726 {"Identifier (LE)", "icmp.ident", FT_UINT16, BASE_DEC_HEX,
1727 NULL, 0x0,
1728 "Identifier (little endian representation)", HFILL}},
1730 {&hf_icmp_seq_num,
1731 {"Sequence number (BE)", "icmp.seq", FT_UINT16,
1732 BASE_DEC_HEX, NULL, 0x0,
1733 "Sequence number (big endian representation)", HFILL}},
1735 {&hf_icmp_seq_num_le,
1736 {"Sequence number (LE)", "icmp.seq_le", FT_UINT16,
1737 BASE_DEC_HEX, NULL,
1738 0x0, "Sequence number (little endian representation)",
1739 HFILL}},
1741 {&hf_icmp_mtu,
1742 {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL,
1743 0x0,
1744 NULL, HFILL}},
1746 {&hf_icmp_redir_gw,
1747 {"Gateway address", "icmp.redir_gw", FT_IPv4, BASE_NONE,
1748 NULL, 0x0,
1749 NULL, HFILL}},
1751 {&hf_icmp_mip_type,
1752 {"Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
1753 VALS(mip_extensions), 0x0, NULL, HFILL}},
1755 {&hf_icmp_mip_length,
1756 {"Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL,
1757 0x0,
1758 NULL, HFILL}},
1760 {&hf_icmp_mip_prefix_length,
1761 {"Prefix Length", "icmp.mip.prefixlength", FT_UINT8,
1762 BASE_DEC, NULL, 0x0,
1763 NULL, HFILL}},
1765 {&hf_icmp_mip_seq,
1766 {"Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC,
1767 NULL, 0x0,
1768 NULL, HFILL}},
1770 {&hf_icmp_mip_life,
1771 {"Registration Lifetime", "icmp.mip.life", FT_UINT16,
1772 BASE_DEC, NULL,
1773 0x0,
1774 NULL, HFILL}},
1776 {&hf_icmp_mip_flags,
1777 {"Flags", "icmp.mip.flags", FT_UINT16, BASE_HEX, NULL,
1778 0x0,
1779 NULL, HFILL}},
1781 {&hf_icmp_mip_r,
1782 {"Registration Required", "icmp.mip.r", FT_BOOLEAN, 16,
1783 NULL, 0x8000,
1784 "Registration with this FA is required", HFILL}},
1786 {&hf_icmp_mip_b,
1787 {"Busy", "icmp.mip.b", FT_BOOLEAN, 16, NULL, 0x4000,
1788 "This FA will not accept requests at this time", HFILL}},
1790 {&hf_icmp_mip_h,
1791 {"Home Agent", "icmp.mip.h", FT_BOOLEAN, 16, NULL, 0x2000,
1792 "Home Agent Services Offered", HFILL}},
1794 {&hf_icmp_mip_f,
1795 {"Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 16, NULL,
1796 0x1000,
1797 "Foreign Agent Services Offered", HFILL}},
1799 {&hf_icmp_mip_m,
1800 {"Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 16,
1801 NULL, 0x0800,
1802 "Minimal encapsulation tunneled datagram support",
1803 HFILL}},
1805 {&hf_icmp_mip_g,
1806 {"GRE", "icmp.mip.g", FT_BOOLEAN, 16, NULL, 0x0400,
1807 "GRE encapsulated tunneled datagram support", HFILL}},
1809 {&hf_icmp_mip_v,
1810 {"VJ Comp", "icmp.mip.v", FT_BOOLEAN, 16, NULL, 0x0200,
1811 "Van Jacobson Header Compression Support", HFILL}},
1813 {&hf_icmp_mip_rt,
1814 {"Reverse tunneling", "icmp.mip.rt", FT_BOOLEAN, 16, NULL,
1815 0x0100,
1816 "Reverse tunneling support", HFILL}},
1818 {&hf_icmp_mip_u,
1819 {"UDP tunneling", "icmp.mip.u", FT_BOOLEAN, 16, NULL,
1820 0x0080,
1821 "UDP tunneling support", HFILL}},
1823 {&hf_icmp_mip_x,
1824 {"Revocation support", "icmp.mip.x", FT_BOOLEAN, 16, NULL,
1825 0x0040,
1826 "Registration revocation support", HFILL}},
1828 {&hf_icmp_mip_reserved,
1829 {"Reserved", "icmp.mip.reserved", FT_UINT16, BASE_HEX,
1830 NULL, 0x003f,
1831 NULL, HFILL}},
1833 {&hf_icmp_mip_coa,
1834 {"Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE,
1835 NULL, 0x0,
1836 NULL, HFILL}},
1838 {&hf_icmp_mip_challenge,
1839 {"Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE,
1840 NULL, 0x0,
1841 NULL, HFILL}},
1843 {&hf_icmp_ext,
1844 {"ICMP Extensions", "icmp.ext", FT_NONE, BASE_NONE, NULL,
1845 0x0,
1846 NULL, HFILL}},
1848 {&hf_icmp_ext_version,
1849 {"Version", "icmp.ext.version", FT_UINT8, BASE_DEC, NULL,
1850 0x0,
1851 NULL, HFILL}},
1853 {&hf_icmp_ext_reserved,
1854 {"Reserved", "icmp.ext.res", FT_UINT16, BASE_HEX, NULL,
1855 0x0fff,
1856 NULL, HFILL}},
1858 {&hf_icmp_ext_checksum,
1859 {"Checksum", "icmp.ext.checksum", FT_UINT16, BASE_HEX,
1860 NULL, 0x0,
1861 NULL, HFILL}},
1863 {&hf_icmp_ext_checksum_bad,
1864 {"Bad Checksum", "icmp.ext.checksum_bad", FT_BOOLEAN,
1865 BASE_NONE, NULL,
1866 0x0,
1867 NULL, HFILL}},
1869 {&hf_icmp_ext_length,
1870 {"Length", "icmp.ext.length", FT_UINT16, BASE_DEC, NULL,
1871 0x0,
1872 NULL, HFILL}},
1874 {&hf_icmp_ext_class,
1875 {"Class", "icmp.ext.class", FT_UINT8, BASE_DEC, NULL, 0x0,
1876 NULL, HFILL}},
1878 {&hf_icmp_ext_c_type,
1879 {"C-Type", "icmp.ext.ctype", FT_UINT8, BASE_DEC, NULL,
1880 0x0,
1881 NULL, HFILL}},
1883 {&hf_icmp_mpls_label,
1884 {"Label", "icmp.mpls.label", FT_UINT24, BASE_DEC, NULL,
1885 0x00fffff0,
1886 NULL, HFILL}},
1888 {&hf_icmp_mpls_exp,
1889 {"Experimental", "icmp.mpls.exp", FT_UINT24, BASE_DEC,
1890 NULL, 0x0e,
1891 NULL, HFILL}},
1893 {&hf_icmp_mpls_s,
1894 {"Stack bit", "icmp.mpls.s", FT_BOOLEAN, 24,
1895 TFS(&tfs_set_notset), 0x01,
1896 NULL, HFILL}},
1898 {&hf_icmp_mpls_ttl,
1899 {"Time to live", "icmp.mpls.ttl", FT_UINT8, BASE_DEC,
1900 NULL, 0x0,
1901 NULL, HFILL}},
1903 {&hf_icmp_resp_in,
1904 {"Response frame", "icmp.resp_in", FT_FRAMENUM, BASE_NONE,
1905 NULL, 0x0,
1906 "The frame number of the corresponding response",
1907 HFILL}},
1909 {&hf_icmp_resp_to,
1910 {"Request frame", "icmp.resp_to", FT_FRAMENUM, BASE_NONE,
1911 NULL, 0x0,
1912 "The frame number of the corresponding request", HFILL}},
1914 {&hf_icmp_resptime,
1915 {"Response time", "icmp.resptime", FT_DOUBLE, BASE_NONE,
1916 NULL, 0x0,
1917 "The time between the request and the response, in ms.",
1918 HFILL}},
1920 {&hf_icmp_data_time,
1921 {"Timestamp from icmp data", "icmp.data_time",
1922 FT_ABSOLUTE_TIME,
1923 ABSOLUTE_TIME_LOCAL, NULL, 0x0,
1924 "The timestamp in the first 8 bytes of the icmp data",
1925 HFILL}},
1927 {&hf_icmp_data_time_relative,
1928 {"Timestamp from icmp data (relative)",
1929 "icmp.data_time_relative",
1930 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
1931 "The timestamp of the packet, relative to the timestamp in the first 8 bytes of the icmp data",
1932 HFILL}},
1934 {&hf_icmp_length,
1935 {"Length of original datagram", "icmp.length", FT_UINT8,
1936 BASE_DEC, NULL,
1937 0x0,
1938 "The length of the original datagram", HFILL}},
1939 {&hf_icmp_int_info_role,
1940 {"Interface Role", "icmp.int_info.role",
1941 FT_UINT8, BASE_DEC, VALS(interface_role_str),
1942 INT_INFO_INTERFACE_ROLE,
1943 NULL, HFILL}},
1944 {&hf_icmp_int_info_reserved,
1945 {"Reserved", "icmp.int_info.reserved",
1946 FT_UINT8, BASE_DEC, NULL, INT_INFO_RESERVED,
1947 NULL, HFILL}},
1948 {&hf_icmp_int_info_ifindex,
1949 {"ifIndex", "icmp.int_info.ifindex", FT_BOOLEAN, 8, NULL,
1950 INT_INFO_IFINDEX,
1951 "True: ifIndex of the interface included; False: ifIndex of the interface not included ",
1952 HFILL}},
1953 {&hf_icmp_int_info_ipaddr,
1954 {"IP Address", "icmp.int_info.ipaddr", FT_BOOLEAN, 8,
1955 NULL,
1956 INT_INFO_IPADDR,
1957 "True: IP Address Sub-Object present; False: IP Address Sub-Object not present",
1958 HFILL}},
1959 {&hf_icmp_int_info_name,
1960 {"Interface Name", "icmp.int_info.name", FT_BOOLEAN, 8,
1961 NULL,
1962 INT_INFO_NAME,
1963 "True: Interface Name Sub-Object present; False: Interface Name Sub-Object not present",
1964 HFILL}},
1965 {&hf_icmp_int_info_mtu,
1966 {"MTU", "icmp.int_info.mtu", FT_BOOLEAN, 8, NULL,
1967 INT_INFO_MTU,
1968 "True: MTU present; False: MTU not present", HFILL}},
1969 {&hf_icmp_int_info_afi,
1970 {"Address Family Identifier", "icmp.int_info.afi",
1971 FT_UINT16, BASE_DEC,
1972 NULL, 0x0,
1973 "Address Family of the interface address", HFILL}},
1974 {&hf_icmp_int_info_ipv4,
1975 {"Source", "icmp.int_info.ipv4", FT_IPv4, BASE_NONE, NULL,
1976 0x0,
1977 NULL, HFILL}},
1978 {&hf_icmp_int_info_ipv6,
1979 {"Source", "icmp.int_info.ipv6", FT_IPv6, BASE_NONE, NULL,
1980 0x0,
1981 NULL, HFILL}}
1984 static gint *ett[] = {
1985 &ett_icmp,
1986 &ett_icmp_mip,
1987 &ett_icmp_mip_flags,
1988 /* MPLS extensions */
1989 &ett_icmp_ext,
1990 &ett_icmp_ext_object,
1991 &ett_icmp_mpls_stack_object,
1992 /* Interface Information Object RFC 5837 */
1993 &ett_icmp_interface_info_object,
1994 &ett_icmp_interface_ipaddr,
1995 &ett_icmp_interface_name
1998 module_t *icmp_module;
2000 proto_icmp =
2001 proto_register_protocol("Internet Control Message Protocol",
2002 "ICMP", "icmp");
2003 proto_register_field_array(proto_icmp, hf, array_length(hf));
2004 proto_register_subtree_array(ett, array_length(ett));
2006 icmp_module = prefs_register_protocol(proto_icmp, NULL);
2008 prefs_register_bool_preference(icmp_module, "favor_icmp_mpls",
2009 "Favor ICMP extensions for MPLS",
2010 "Whether the 128th and following bytes of the ICMP payload should be decoded as MPLS extensions or as a portion of the original packet",
2011 &favor_icmp_mpls_ext);
2013 register_dissector("icmp", dissect_icmp, proto_icmp);
2014 icmp_tap = register_tap("icmp");
2017 void proto_reg_handoff_icmp(void)
2019 dissector_handle_t icmp_handle;
2022 * Get handle for the IP dissector.
2024 ip_handle = find_dissector("ip");
2025 icmp_handle = find_dissector("icmp");
2026 data_handle = find_dissector("data");
2028 dissector_add_uint("ip.proto", IP_PROTO_ICMP, icmp_handle);