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