2 * Routines for IP and miscellaneous IP protocol packet disassembly
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 * by Maria-Luiza Crivat <luizacri@gmail.com>
14 * & Brice Augustin <bricecotte@gmail.com>
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #include <epan/packet.h>
40 #include <epan/addr_resolv.h>
41 #include <epan/ipproto.h>
42 #include <epan/ip_opts.h>
43 #include <epan/prefs.h>
44 #include <epan/reassemble.h>
45 #include <epan/etypes.h>
46 #include <epan/greproto.h>
47 #include <epan/ppptypes.h>
48 #include <epan/llcsaps.h>
49 #include <epan/aftypes.h>
50 #include <epan/arcnet_pids.h>
51 #include "packet-ip.h"
52 #include "packet-ipsec.h"
53 #include <epan/in_cksum.h>
54 #include <epan/nlpid.h>
56 #include <epan/emem.h>
57 #include <epan/nstime.h>
59 static int ip_tap = -1;
61 static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
63 /* Decode the old IPv4 TOS field as the DiffServ DS Field (RFC2474/2475) */
64 static gboolean g_ip_dscp_actif = TRUE;
66 /* Defragment fragmented IP datagrams */
67 static gboolean ip_defragment = TRUE;
69 /* Place IP summary in proto tree */
70 static gboolean ip_summary_in_tree = TRUE;
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 /* Perform IP checksum */
77 static gboolean ip_check_checksum = TRUE;
79 static int proto_ip = -1;
80 static int hf_ip_version = -1;
81 static int hf_ip_hdr_len = -1;
82 static int hf_ip_dsfield = -1;
83 static int hf_ip_dsfield_dscp = -1;
84 static int hf_ip_dsfield_ect = -1;
85 static int hf_ip_dsfield_ce = -1;
86 static int hf_ip_tos = -1;
87 static int hf_ip_tos_precedence = -1;
88 static int hf_ip_tos_delay = -1;
89 static int hf_ip_tos_throughput = -1;
90 static int hf_ip_tos_reliability = -1;
91 static int hf_ip_tos_cost = -1;
92 static int hf_ip_len = -1;
93 static int hf_ip_id = -1;
94 static int hf_ip_dst = -1;
95 static int hf_ip_dst_host = -1;
96 static int hf_ip_src = -1;
97 static int hf_ip_src_host = -1;
98 static int hf_ip_addr = -1;
99 static int hf_ip_host = -1;
100 static int hf_ip_flags = -1;
101 static int hf_ip_flags_rf = -1;
102 static int hf_ip_flags_df = -1;
103 static int hf_ip_flags_mf = -1;
104 static int hf_ip_frag_offset = -1;
105 static int hf_ip_ttl = -1;
106 static int hf_ip_proto = -1;
107 static int hf_ip_checksum = -1;
108 static int hf_ip_checksum_good = -1;
109 static int hf_ip_checksum_bad = -1;
110 static int hf_ip_fragments = -1;
111 static int hf_ip_fragment = -1;
112 static int hf_ip_fragment_overlap = -1;
113 static int hf_ip_fragment_overlap_conflict = -1;
114 static int hf_ip_fragment_multiple_tails = -1;
115 static int hf_ip_fragment_too_long_fragment = -1;
116 static int hf_ip_fragment_error = -1;
117 static int hf_ip_reassembled_in = -1;
119 static gint ett_ip = -1;
120 static gint ett_ip_dsfield = -1;
121 static gint ett_ip_tos = -1;
122 static gint ett_ip_off = -1;
123 static gint ett_ip_options = -1;
124 static gint ett_ip_option_sec = -1;
125 static gint ett_ip_option_route = -1;
126 static gint ett_ip_option_timestamp = -1;
127 static gint ett_ip_fragments = -1;
128 static gint ett_ip_fragment = -1;
129 static gint ett_ip_checksum = -1;
131 static const fragment_items ip_frag_items = {
136 &hf_ip_fragment_overlap,
137 &hf_ip_fragment_overlap_conflict,
138 &hf_ip_fragment_multiple_tails,
139 &hf_ip_fragment_too_long_fragment,
140 &hf_ip_fragment_error,
141 &hf_ip_reassembled_in,
145 static dissector_table_t ip_dissector_table;
147 static dissector_handle_t ip_handle;
148 static dissector_handle_t ipv6_handle;
149 static dissector_handle_t data_handle;
151 static int proto_icmp = -1;
152 static int hf_icmp_type = -1;
153 static int hf_icmp_code = -1;
154 static int hf_icmp_checksum = -1;
155 static int hf_icmp_checksum_bad = -1;
156 static int hf_icmp_ident = -1;
157 static int hf_icmp_seq_num = -1;
158 static int hf_icmp_mtu = -1;
159 static int hf_icmp_redir_gw = -1;
163 static int hf_icmp_mip_type = -1;
164 static int hf_icmp_mip_length = -1;
165 static int hf_icmp_mip_prefix_length = -1;
166 static int hf_icmp_mip_seq = -1;
167 static int hf_icmp_mip_life = -1;
168 static int hf_icmp_mip_flags = -1;
169 static int hf_icmp_mip_r = -1;
170 static int hf_icmp_mip_b = -1;
171 static int hf_icmp_mip_h = -1;
172 static int hf_icmp_mip_f = -1;
173 static int hf_icmp_mip_m = -1;
174 static int hf_icmp_mip_g = -1;
175 static int hf_icmp_mip_v = -1;
176 static int hf_icmp_mip_rt = -1;
177 static int hf_icmp_mip_reserved = -1;
178 static int hf_icmp_mip_coa = -1;
179 static int hf_icmp_mip_challenge = -1;
181 /* MPLS extensions */
182 static int hf_icmp_mpls = -1;
183 static int hf_icmp_mpls_version = -1;
184 static int hf_icmp_mpls_reserved = -1;
185 static int hf_icmp_mpls_checksum = -1;
186 static int hf_icmp_mpls_checksum_bad = -1;
187 static int hf_icmp_mpls_length = -1;
188 static int hf_icmp_mpls_class = -1;
189 static int hf_icmp_mpls_c_type = -1;
190 static int hf_icmp_mpls_label = -1;
191 static int hf_icmp_mpls_exp = -1;
192 static int hf_icmp_mpls_s = -1;
193 static int hf_icmp_mpls_ttl = -1;
195 static gint ett_icmp = -1;
196 static gint ett_icmp_mip = -1;
197 static gint ett_icmp_mip_flags = -1;
198 /* MPLS extensions */
199 static gint ett_icmp_mpls = -1;
200 static gint ett_icmp_mpls_object = -1;
201 static gint ett_icmp_mpls_stack_object = -1;
203 /* ICMP definitions */
205 #define ICMP_ECHOREPLY 0
206 #define ICMP_UNREACH 3
207 #define ICMP_SOURCEQUENCH 4
208 #define ICMP_REDIRECT 5
210 #define ICMP_RTRADVERT 9
211 #define ICMP_RTRSOLICIT 10
212 #define ICMP_TIMXCEED 11
213 #define ICMP_PARAMPROB 12
214 #define ICMP_TSTAMP 13
215 #define ICMP_TSTAMPREPLY 14
217 #define ICMP_IREQREPLY 16
218 #define ICMP_MASKREQ 17
219 #define ICMP_MASKREPLY 18
221 /* ICMP UNREACHABLE */
223 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
224 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
225 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
226 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
227 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
228 #define ICMP_SR_FAILED 5 /* Source Route failed */
229 #define ICMP_NET_UNKNOWN 6
230 #define ICMP_HOST_UNKNOWN 7
231 #define ICMP_HOST_ISOLATED 8
232 #define ICMP_NET_ANO 9
233 #define ICMP_HOST_ANO 10
234 #define ICMP_NET_UNR_TOS 11
235 #define ICMP_HOST_UNR_TOS 12
236 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
237 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
238 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
241 /* IP structs and definitions */
243 /* Offsets of fields within an IP header. */
255 /* Minimum IP header length. */
256 #define IPH_MIN_LEN 20
259 #define IP_RF 0x8000 /* Flag: "Reserved bit" */
260 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
261 #define IP_MF 0x2000 /* Flag: "More Fragments" */
262 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
264 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
265 #define IPDSFIELD_DSCP_MASK 0xFC
266 #define IPDSFIELD_ECN_MASK 0x03
267 #define IPDSFIELD_DSCP_SHIFT 2
268 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
269 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
270 #define IPDSFIELD_DSCP_DEFAULT 0x00
271 #define IPDSFIELD_DSCP_CS1 0x08
272 #define IPDSFIELD_DSCP_CS2 0x10
273 #define IPDSFIELD_DSCP_CS3 0x18
274 #define IPDSFIELD_DSCP_CS4 0x20
275 #define IPDSFIELD_DSCP_CS5 0x28
276 #define IPDSFIELD_DSCP_CS6 0x30
277 #define IPDSFIELD_DSCP_CS7 0x38
278 #define IPDSFIELD_DSCP_AF11 0x0A
279 #define IPDSFIELD_DSCP_AF12 0x0C
280 #define IPDSFIELD_DSCP_AF13 0x0E
281 #define IPDSFIELD_DSCP_AF21 0x12
282 #define IPDSFIELD_DSCP_AF22 0x14
283 #define IPDSFIELD_DSCP_AF23 0x16
284 #define IPDSFIELD_DSCP_AF31 0x1A
285 #define IPDSFIELD_DSCP_AF32 0x1C
286 #define IPDSFIELD_DSCP_AF33 0x1E
287 #define IPDSFIELD_DSCP_AF41 0x22
288 #define IPDSFIELD_DSCP_AF42 0x24
289 #define IPDSFIELD_DSCP_AF43 0x26
290 #define IPDSFIELD_DSCP_EF 0x2E
291 #define IPDSFIELD_ECT_MASK 0x02
292 #define IPDSFIELD_CE_MASK 0x01
294 /* IP TOS, superseded by the DS Field, RFC 2474. */
295 #define IPTOS_TOS_MASK 0x1E
296 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
297 #define IPTOS_NONE 0x00
298 #define IPTOS_LOWCOST 0x02
299 #define IPTOS_RELIABILITY 0x04
300 #define IPTOS_THROUGHPUT 0x08
301 #define IPTOS_LOWDELAY 0x10
302 #define IPTOS_SECURITY 0x1E
304 #define IPTOS_PREC_MASK 0xE0
305 #define IPTOS_PREC_SHIFT 5
306 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
307 #define IPTOS_PREC_NETCONTROL 7
308 #define IPTOS_PREC_INTERNETCONTROL 6
309 #define IPTOS_PREC_CRITIC_ECP 5
310 #define IPTOS_PREC_FLASHOVERRIDE 4
311 #define IPTOS_PREC_FLASH 3
312 #define IPTOS_PREC_IMMEDIATE 2
313 #define IPTOS_PREC_PRIORITY 1
314 #define IPTOS_PREC_ROUTINE 0
317 #define IPOPT_COPY 0x80
319 #define IPOPT_CONTROL 0x00
320 #define IPOPT_RESERVED1 0x20
321 #define IPOPT_MEASUREMENT 0x40
322 #define IPOPT_RESERVED2 0x60
324 #define IPOPT_END (0 |IPOPT_CONTROL)
325 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
326 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
327 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
328 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
329 #define IPOPT_RR (7 |IPOPT_CONTROL)
330 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
331 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
332 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
334 /* IP option lengths */
335 #define IPOLEN_SEC 11
336 #define IPOLEN_LSRR_MIN 3
337 #define IPOLEN_TIMESTAMP_MIN 5
338 #define IPOLEN_RR_MIN 3
340 #define IPOLEN_SSRR_MIN 3
343 #define IPSEC_UNCLASSIFIED 0x0000
344 #define IPSEC_CONFIDENTIAL 0xF135
345 #define IPSEC_EFTO 0x789A
346 #define IPSEC_MMMM 0xBC4D
347 #define IPSEC_RESTRICTED 0xAF13
348 #define IPSEC_SECRET 0xD788
349 #define IPSEC_TOPSECRET 0x6BC5
350 #define IPSEC_RESERVED1 0x35E2
351 #define IPSEC_RESERVED2 0x9AF1
352 #define IPSEC_RESERVED3 0x4D78
353 #define IPSEC_RESERVED4 0x24BD
354 #define IPSEC_RESERVED5 0x135E
355 #define IPSEC_RESERVED6 0x89AF
356 #define IPSEC_RESERVED7 0xC4D6
357 #define IPSEC_RESERVED8 0xE26B
359 #define IPOPT_TS_TSONLY 0 /* timestamps only */
360 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
361 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
364 * defragmentation of IPv4
366 static GHashTable *ip_fragment_table = NULL;
367 static GHashTable *ip_reassembled_table = NULL;
370 ip_defragment_init(void)
372 fragment_table_init(&ip_fragment_table);
373 reassembled_table_init(&ip_reassembled_table);
377 capture_ip(const guchar *pd, int offset, int len, packet_counts *ld) {
378 if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
382 switch (pd[offset + 9]) {
387 case IP_PROTO_UDPLITE:
391 case IP_PROTO_ICMPV6: /* XXX - separate counters? */
412 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
413 guint optlen, packet_info *pinfo _U_,
414 proto_tree *opt_tree)
416 proto_tree *field_tree = NULL;
419 static const value_string secl_vals[] = {
420 {IPSEC_UNCLASSIFIED, "Unclassified"},
421 {IPSEC_CONFIDENTIAL, "Confidential"},
422 {IPSEC_EFTO, "EFTO" },
423 {IPSEC_MMMM, "MMMM" },
424 {IPSEC_RESTRICTED, "Restricted" },
425 {IPSEC_SECRET, "Secret" },
426 {IPSEC_TOPSECRET, "Top secret" },
427 {IPSEC_RESERVED1, "Reserved" },
428 {IPSEC_RESERVED2, "Reserved" },
429 {IPSEC_RESERVED3, "Reserved" },
430 {IPSEC_RESERVED4, "Reserved" },
431 {IPSEC_RESERVED5, "Reserved" },
432 {IPSEC_RESERVED6, "Reserved" },
433 {IPSEC_RESERVED7, "Reserved" },
434 {IPSEC_RESERVED8, "Reserved" },
437 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
438 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
441 val = tvb_get_ntohs(tvb, offset);
442 proto_tree_add_text(field_tree, tvb, offset, 2,
443 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
446 val = tvb_get_ntohs(tvb, offset);
447 proto_tree_add_text(field_tree, tvb, offset, 2,
448 "Compartments: %u", val);
451 proto_tree_add_text(field_tree, tvb, offset, 2,
452 "Handling restrictions: %c%c",
453 tvb_get_guint8(tvb, offset),
454 tvb_get_guint8(tvb, offset + 1));
457 proto_tree_add_text(field_tree, tvb, offset, 3,
458 "Transmission control code: %c%c%c",
459 tvb_get_guint8(tvb, offset),
460 tvb_get_guint8(tvb, offset + 1),
461 tvb_get_guint8(tvb, offset + 2));
465 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
466 guint optlen, packet_info *pinfo _U_,
467 proto_tree *opt_tree)
469 proto_tree *field_tree = NULL;
475 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
477 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
479 optoffset += 2; /* skip past type and length */
480 optlen -= 2; /* subtract size of type and length */
482 ptr = tvb_get_guint8(tvb, offset + optoffset);
483 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
484 "Pointer: %d%s", ptr,
485 ((ptr < 4) ? " (points before first address)" :
486 ((ptr & 3) ? " (points to middle of address)" : "")));
489 ptr--; /* ptr is 1-origin */
493 proto_tree_add_text(field_tree, tvb, offset, optlen,
494 "(suboption would go past end of option)");
498 addr = tvb_get_ipv4(tvb, offset + optoffset);
499 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
501 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
502 ((optoffset == ptr) ? " <- (current)" : ""));
509 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
510 guint optlen, packet_info *pinfo _U_,
511 proto_tree *opt_tree)
513 proto_tree_add_text(opt_tree, tvb, offset, optlen,
514 "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
519 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
520 int offset, guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
522 proto_tree *field_tree = NULL;
527 static const value_string flag_vals[] = {
528 {IPOPT_TS_TSONLY, "Time stamps only" },
529 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
530 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
535 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
536 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
538 optoffset += 2; /* skip past type and length */
539 optlen -= 2; /* subtract size of type and length */
541 ptr = tvb_get_guint8(tvb, offset + optoffset);
542 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
543 "Pointer: %d%s", ptr,
544 ((ptr < 5) ? " (points before first address)" :
545 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
548 ptr--; /* ptr is 1-origin */
550 flg = tvb_get_guint8(tvb, offset + optoffset);
551 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
552 "Overflow: %u", flg >> 4);
554 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
555 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
560 if (flg == IPOPT_TS_TSANDADDR) {
562 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
563 "(suboption would go past end of option)");
566 addr = tvb_get_ipv4(tvb, offset + optoffset);
567 ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
569 proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
570 "Address = %s, time stamp = %u",
571 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
576 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
577 "(suboption would go past end of option)");
580 ts = tvb_get_ntohl(tvb, offset + optoffset);
582 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
583 "Time stamp = %u", ts);
590 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
591 guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
593 /* Router-Alert, as defined by RFC2113 */
594 int opt = tvb_get_ntohs(tvb, offset + 2);
595 static const value_string ra_opts[] = {
596 {0, "Every router examines packet"},
600 proto_tree_add_text(opt_tree, tvb, offset, optlen,
601 "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
605 static const ip_tcp_opt ipopts[] = {
628 dissect_ipopt_security
632 "Strict source route",
633 &ett_ip_option_route,
640 "Loose source route",
641 &ett_ip_option_route,
649 &ett_ip_option_route,
665 &ett_ip_option_timestamp,
667 IPOLEN_TIMESTAMP_MIN,
668 dissect_ipopt_timestamp
680 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
682 /* Dissect the IP or TCP options in a packet. */
684 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
685 const ip_tcp_opt *opttab, int nopts, int eol,
686 packet_info *pinfo, proto_tree *opt_tree)
689 const ip_tcp_opt *optp;
690 opt_len_type len_type;
693 #define NAME_STR_LEN 7+1+1+2+2+1+1 /* "Unknown (0x%02x)" */
695 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
696 int, guint, packet_info *, proto_tree *);
699 name_str=ep_alloc(NAME_STR_LEN);
701 opt = tvb_get_guint8(tvb, offset);
702 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
703 if (optp->optcode == opt)
706 if (optp == &opttab[nopts]) {
707 /* We assume that the only NO_LENGTH options are EOL and NOP options,
708 so that we can treat unknown options as VARIABLE_LENGTH with a
709 minimum of 2, and at least be able to move on to the next option
710 by using the length in the option. */
711 optp = NULL; /* indicate that we don't know this option */
712 len_type = VARIABLE_LENGTH;
714 g_snprintf(name_str, NAME_STR_LEN, "Unknown (0x%02x)", opt);
718 len_type = optp->len_type;
719 optlen = optp->optlen;
721 dissect = optp->dissect;
723 --length; /* account for type byte */
724 if (len_type != NO_LENGTH) {
725 /* Option has a length. Is it in the packet? */
727 /* Bogus - packet must at least include option code byte and
729 proto_tree_add_text(opt_tree, tvb, offset, 1,
730 "%s (length byte past end of options)", name);
733 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
734 --length; /* account for length byte */
736 /* Bogus - option length is too short to include option code and
738 proto_tree_add_text(opt_tree, tvb, offset, 2,
739 "%s (with too-short option length = %u byte%s)", name,
740 len, plurality(len, "", "s"));
742 } else if (len - 2 > length) {
743 /* Bogus - option goes past the end of the header. */
744 proto_tree_add_text(opt_tree, tvb, offset, length,
745 "%s (option length = %u byte%s says option goes past end of options)",
746 name, len, plurality(len, "", "s"));
748 } else if (len_type == FIXED_LENGTH && len != optlen) {
749 /* Bogus - option length isn't what it's supposed to be for this
751 proto_tree_add_text(opt_tree, tvb, offset, len,
752 "%s (with option length = %u byte%s; should be %u)", name,
753 len, plurality(len, "", "s"), optlen);
755 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
756 /* Bogus - option length is less than what it's supposed to be for
758 proto_tree_add_text(opt_tree, tvb, offset, len,
759 "%s (with option length = %u byte%s; should be >= %u)", name,
760 len, plurality(len, "", "s"), optlen);
764 proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
765 name, len, plurality(len, "", "s"));
767 if (dissect != NULL) {
768 /* Option has a dissector. */
769 (*dissect)(optp, tvb, offset, len, pinfo, opt_tree);
771 /* Option has no data, hence no dissector. */
772 proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
775 len -= 2; /* subtract size of type and length */
780 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
788 const value_string dscp_vals[] = {
789 { IPDSFIELD_DSCP_DEFAULT, "Default" },
790 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
791 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
792 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
793 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
794 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
795 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
796 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
797 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
798 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
799 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
800 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
801 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
802 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
803 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
804 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
805 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
806 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
807 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
808 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
809 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
812 static const value_string precedence_vals[] = {
813 { IPTOS_PREC_ROUTINE, "routine" },
814 { IPTOS_PREC_PRIORITY, "priority" },
815 { IPTOS_PREC_IMMEDIATE, "immediate" },
816 { IPTOS_PREC_FLASH, "flash" },
817 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
818 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
819 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
820 { IPTOS_PREC_NETCONTROL, "network control" },
823 static const value_string iptos_vals[] = {
824 { IPTOS_NONE, "None" },
825 { IPTOS_LOWCOST, "Minimize cost" },
826 { IPTOS_RELIABILITY, "Maximize reliability" },
827 { IPTOS_THROUGHPUT, "Maximize throughput" },
828 { IPTOS_LOWDELAY, "Minimize delay" },
829 { IPTOS_SECURITY, "Maximize security" },
833 static const true_false_string tos_set_low = {
838 static const true_false_string tos_set_high = {
843 static guint16 ip_checksum(const guint8 *ptr, int len)
847 cksum_vec[0].ptr = ptr;
848 cksum_vec[0].len = len;
849 return in_cksum(&cksum_vec[0], 1);
853 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
855 proto_tree *ip_tree = NULL, *field_tree;
856 proto_item *ti = NULL, *tf;
863 fragment_data *ipfd_head=NULL;
865 gboolean update_col_info = TRUE;
866 gboolean save_fragmented;
867 static e_ip eip_arr[4];
868 static int eip_current=0;
870 const guchar *src_addr, *dst_addr;
871 guint32 src32, dst32;
874 proto_tree *checksum_tree;
882 iph=&eip_arr[eip_current];
884 if (check_col(pinfo->cinfo, COL_PROTOCOL))
885 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
886 if (check_col(pinfo->cinfo, COL_INFO))
887 col_clear(pinfo->cinfo, COL_INFO);
889 iph->ip_v_hl = tvb_get_guint8(tvb, offset);
890 if ( hi_nibble(iph->ip_v_hl) == 6){
891 call_dissector(ipv6_handle, tvb, pinfo, parent_tree);
895 hlen = lo_nibble(iph->ip_v_hl) * 4; /* IP header length, in bytes */
898 ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
899 ip_tree = proto_item_add_subtree(ti, ett_ip);
901 proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1,
902 hi_nibble(iph->ip_v_hl));
905 /* if IP is not referenced from any filters we dont need to worry about
906 generating any tree items. We must do this after we created the actual
907 protocol above so that proto hier stat still works though.
909 if(!proto_field_is_referenced(parent_tree, proto_ip)){
913 if (hlen < IPH_MIN_LEN) {
914 if (check_col(pinfo->cinfo, COL_INFO))
915 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
918 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
919 "Header length: %u bytes (bogus, must be at least %u)", hlen,
926 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
927 "Header length: %u bytes", hlen);
930 iph->ip_tos = tvb_get_guint8(tvb, offset + 1);
932 if (g_ip_dscp_actif) {
933 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph->ip_tos,
934 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph->ip_tos,
935 IPDSFIELD_DSCP(iph->ip_tos), val_to_str(IPDSFIELD_DSCP(iph->ip_tos), dscp_vals,
936 "Unknown DSCP"),IPDSFIELD_ECN(iph->ip_tos));
938 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
939 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph->ip_tos);
940 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph->ip_tos);
941 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph->ip_tos);
943 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph->ip_tos,
944 "Type of service: 0x%02x (%s)", iph->ip_tos,
945 val_to_str( IPTOS_TOS(iph->ip_tos), iptos_vals, "Unknown") );
947 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
948 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph->ip_tos);
949 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph->ip_tos);
950 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph->ip_tos);
951 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph->ip_tos);
952 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph->ip_tos);
956 /* Length of IP datagram.
957 XXX - what if this is greater than the reported length of the
958 tvbuff? This could happen, for example, in an IP datagram
959 inside an ICMP datagram; we need to somehow let the
960 dissector we call know that, as it might want to avoid
961 doing its checksumming. */
962 iph->ip_len = tvb_get_ntohs(tvb, offset + 2);
964 /* Adjust the length of this tvbuff to include only the IP datagram. */
965 set_actual_length(tvb, iph->ip_len);
967 if (iph->ip_len < hlen) {
968 if (check_col(pinfo->cinfo, COL_INFO))
969 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP length (%u, less than header length %u)",
972 proto_tree_add_uint_format(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len,
973 "Total length: %u bytes (bogus, less than header length %u)", iph->ip_len,
979 proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len);
981 iph->ip_id = tvb_get_ntohs(tvb, offset + 4);
983 proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph->ip_id);
985 iph->ip_off = tvb_get_ntohs(tvb, offset + 6);
987 flags = (iph->ip_off & (IP_RF | IP_DF | IP_MF)) >> 12;
988 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
989 field_tree = proto_item_add_subtree(tf, ett_ip_off);
990 proto_tree_add_boolean(field_tree, hf_ip_flags_rf, tvb, offset + 6, 1, flags);
991 if (flags & (IP_DF>>12)) proto_item_append_text(tf, " (Don't Fragment)");
992 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags);
993 if (flags & (IP_MF>>12)) proto_item_append_text(tf, " (More Fragments)");
994 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags);
996 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
997 (iph->ip_off & IP_OFFSET)*8);
1001 proto_tree_add_item(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, FALSE);
1003 iph->ip_p = tvb_get_guint8(tvb, offset + 9);
1005 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph->ip_p,
1006 "Protocol: %s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
1009 iph->ip_sum = tvb_get_ntohs(tvb, offset + 10);
1012 * If we have the entire IP header available, check the checksum.
1014 if (ip_check_checksum && tvb_bytes_exist(tvb, offset, hlen)) {
1015 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
1018 item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
1019 "Header checksum: 0x%04x [correct]", iph->ip_sum);
1020 checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
1021 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, TRUE);
1022 PROTO_ITEM_SET_GENERATED(item);
1023 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, FALSE);
1024 PROTO_ITEM_SET_GENERATED(item);
1026 item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
1027 "Header checksum: 0x%04x [incorrect, should be 0x%04x]", iph->ip_sum,
1028 in_cksum_shouldbe(iph->ip_sum, ipsum));
1029 checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
1030 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, FALSE);
1031 PROTO_ITEM_SET_GENERATED(item);
1032 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
1033 PROTO_ITEM_SET_GENERATED(item);
1039 item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
1040 "Header checksum: 0x%04x [%s]", iph->ip_sum,
1041 ip_check_checksum ? "not all data available" : "validation disabled");
1042 checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
1043 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, FALSE);
1044 PROTO_ITEM_SET_GENERATED(item);
1045 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, FALSE);
1046 PROTO_ITEM_SET_GENERATED(item);
1049 src_addr = tvb_get_ptr(tvb, offset + IPH_SRC, 4);
1050 src32 = tvb_get_ntohl(tvb, offset + IPH_SRC);
1051 SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, src_addr);
1052 SET_ADDRESS(&pinfo->src, AT_IPv4, 4, src_addr);
1053 SET_ADDRESS(&iph->ip_src, AT_IPv4, 4, src_addr);
1055 memcpy(&addr, iph->ip_src.data, 4);
1056 if (ip_summary_in_tree) {
1057 proto_item_append_text(ti, ", Src: %s (%s)",
1058 get_hostname(addr), ip_to_str(iph->ip_src.data));
1060 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, addr);
1061 item = proto_tree_add_ipv4(ip_tree, hf_ip_addr, tvb, offset + 12, 4, addr);
1062 PROTO_ITEM_SET_HIDDEN(item);
1063 item = proto_tree_add_string(ip_tree, hf_ip_src_host, tvb, offset + 12, 4, get_hostname(addr));
1064 PROTO_ITEM_SET_GENERATED(item);
1065 PROTO_ITEM_SET_HIDDEN(item);
1066 item = proto_tree_add_string(ip_tree, hf_ip_host, tvb, offset + 12, 4, get_hostname(addr));
1067 PROTO_ITEM_SET_GENERATED(item);
1068 PROTO_ITEM_SET_HIDDEN(item);
1070 dst_addr = tvb_get_ptr(tvb, offset + IPH_DST, 4);
1071 dst32 = tvb_get_ntohl(tvb, offset + IPH_DST);
1072 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, dst_addr);
1073 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, dst_addr);
1074 SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, dst_addr);
1077 memcpy(&addr, iph->ip_dst.data, 4);
1078 if (ip_summary_in_tree) {
1079 proto_item_append_text(ti, ", Dst: %s (%s)",
1080 get_hostname(addr), ip_to_str(iph->ip_dst.data));
1082 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, addr);
1083 item = proto_tree_add_ipv4(ip_tree, hf_ip_addr, tvb, offset + 16, 4, addr);
1084 PROTO_ITEM_SET_HIDDEN(item);
1085 item = proto_tree_add_string(ip_tree, hf_ip_dst_host, tvb, offset + 16, 4, get_hostname(addr));
1086 PROTO_ITEM_SET_GENERATED(item);
1087 PROTO_ITEM_SET_HIDDEN(item);
1088 item = proto_tree_add_string(ip_tree, hf_ip_host, tvb, offset + 16, 4, get_hostname(addr));
1089 PROTO_ITEM_SET_GENERATED(item);
1090 PROTO_ITEM_SET_HIDDEN(item);
1094 /* Decode IP options, if any. */
1095 if (hlen > IPH_MIN_LEN) {
1096 /* There's more than just the fixed-length header. Decode the
1098 optlen = hlen - IPH_MIN_LEN; /* length of options, in bytes */
1099 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
1100 "Options: (%u bytes)", optlen);
1101 field_tree = proto_item_add_subtree(tf, ett_ip_options);
1102 dissect_ip_tcp_options(tvb, offset + 20, optlen,
1103 ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
1107 pinfo->ipproto = iph->ip_p;
1109 pinfo->iplen = iph->ip_len;
1111 pinfo->iphdrlen = hlen;
1113 /* Skip over header + options */
1115 nxt = iph->ip_p; /* XXX - what if this isn't the same for all fragments? */
1117 /* If ip_defragment is on, this is a fragment, we have all the data
1118 * in the fragment, and the header checksum is valid, then just add
1119 * the fragment to the hashtable.
1121 save_fragmented = pinfo->fragmented;
1122 if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
1123 tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
1125 ipfd_head = fragment_add_check(tvb, offset, pinfo,
1126 iph->ip_p ^ iph->ip_id ^ src32 ^ dst32,
1128 ip_reassembled_table,
1129 (iph->ip_off & IP_OFFSET)*8,
1130 pinfo->iplen - pinfo->iphdrlen,
1131 iph->ip_off & IP_MF);
1133 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv4",
1134 ipfd_head, &ip_frag_items, &update_col_info, ip_tree);
1136 /* If this is the first fragment, dissect its contents, otherwise
1137 just show it as a fragment.
1139 XXX - if we eventually don't save the reassembled contents of all
1140 fragmented datagrams, we may want to always reassemble. */
1141 if (iph->ip_off & IP_OFFSET) {
1142 /* Not the first fragment - don't dissect it. */
1145 /* First fragment, or not fragmented. Dissect what we have here. */
1147 /* Get a tvbuff for the payload. */
1148 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1151 * If this is the first fragment, but not the only fragment,
1152 * tell the next protocol that.
1154 if (iph->ip_off & IP_MF)
1155 pinfo->fragmented = TRUE;
1157 pinfo->fragmented = FALSE;
1161 if (next_tvb == NULL) {
1162 /* Just show this as a fragment. */
1163 if (check_col(pinfo->cinfo, COL_INFO)) {
1164 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1165 ipprotostr(iph->ip_p), iph->ip_p, (iph->ip_off & IP_OFFSET) * 8);
1167 if( ipfd_head && ipfd_head->reassembled_in != pinfo->fd->num ){
1168 if (check_col(pinfo->cinfo, COL_INFO)) {
1169 col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]",
1170 ipfd_head->reassembled_in);
1174 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
1176 pinfo->fragmented = save_fragmented;
1180 /* Hand off to the next protocol.
1182 XXX - setting the columns only after trying various dissectors means
1183 that if one of those dissectors throws an exception, the frame won't
1184 even be labelled as an IP frame; ideally, if a frame being dissected
1185 throws an exception, it'll be labelled as a mangled frame of the
1186 type in question. */
1187 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, parent_tree)) {
1188 /* Unknown protocol */
1189 if (update_col_info) {
1190 if (check_col(pinfo->cinfo, COL_INFO))
1191 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
1193 call_dissector(data_handle,next_tvb, pinfo, parent_tree);
1195 pinfo->fragmented = save_fragmented;
1198 tap_queue_packet(ip_tap, pinfo, iph);
1202 #define ICMP_MIP_EXTENSION_PAD 0
1203 #define ICMP_MIP_MOB_AGENT_ADV 16
1204 #define ICMP_MIP_PREFIX_LENGTHS 19
1205 #define ICMP_MIP_CHALLENGE 24
1207 static value_string mip_extensions[] = {
1208 { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
1209 { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1211 { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
1212 { ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
1217 * Dissect the mobile ip advertisement extensions.
1220 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1226 proto_tree *mip_tree=NULL;
1227 proto_tree *flags_tree=NULL;
1231 /* Not much to do if we're not parsing everything */
1234 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1236 type = tvb_get_guint8(tvb, offset + 0);
1238 length = tvb_get_guint8(tvb, offset + 1);
1242 ti = proto_tree_add_text(tree, tvb, offset,
1243 type?(length + 2):1,
1245 val_to_str(type, mip_extensions,
1247 mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1251 case ICMP_MIP_EXTENSION_PAD:
1252 /* One byte padding extension */
1253 /* Add our fields */
1255 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1259 case ICMP_MIP_MOB_AGENT_ADV:
1260 /* Mobility Agent Advertisement Extension (RFC 2002)*/
1261 /* Add our fields */
1263 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1267 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1270 /* sequence number */
1271 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset,
1274 /* Registration Lifetime */
1275 proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset,
1279 flags = tvb_get_guint8(tvb, offset);
1280 ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1282 flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1283 proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1284 proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1285 proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1286 proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1287 proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1288 proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1289 proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1290 proto_tree_add_boolean(flags_tree, hf_icmp_mip_rt, tvb, offset, 1, flags);
1295 proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset,
1300 numCOAs = (length - 6) / 4;
1301 for (i=0; i<numCOAs; i++) {
1302 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset,
1307 case ICMP_MIP_PREFIX_LENGTHS:
1308 /* Prefix-Lengths Extension (RFC 2002)*/
1309 /* Add our fields */
1311 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1315 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1319 /* prefix lengths */
1320 for(i=0; i<length; i++) {
1321 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1326 case ICMP_MIP_CHALLENGE:
1327 /* Challenge Extension (RFC 3012)*/
1329 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1333 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1337 proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset,
1343 g_warning("Unknown type(%u)! I hope the length is right (%u)",
1345 offset += length + 2;
1350 } /* dissect_mip_extensions */
1352 #define MPLS_STACK_ENTRY_OBJECT_CLASS 1
1353 #define MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS 2
1355 #define MPLS_STACK_ENTRY_C_TYPE 1
1356 #define MPLS_EXTENDED_PAYLOAD_C_TYPE 1
1358 /* XXX no header defines these macros ??? */
1360 #define min(a,b) (((a)<(b))?(a):(b))
1364 #define max(a,b) (((a)>(b))?(a):(b))
1368 * Dissect the MPLS extensions
1371 dissect_mpls_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1379 guint16 cksum, computed_cksum;
1380 guint16 obj_length, obj_trunc_length;
1381 proto_item *ti, *tf_object, *tf_entry;
1382 proto_tree *mpls_tree=NULL, *mpls_object_tree, *mpls_stack_object_tree;
1383 guint obj_end_offset;
1384 guint reported_length;
1386 gboolean unknown_object;
1391 reported_length = tvb_reported_length_remaining(tvb, offset);
1393 if (reported_length < 4 /* Common header */)
1395 proto_tree_add_text(tree, tvb, offset,
1397 "MPLS Extensions (truncated)");
1401 /* Add a tree for the MPLS extensions */
1402 ti = proto_tree_add_none_format(tree, hf_icmp_mpls, tvb,
1403 offset, reported_length, "MPLS Extensions");
1405 mpls_tree = proto_item_add_subtree(ti, ett_icmp_mpls);
1408 version = hi_nibble(tvb_get_guint8(tvb, offset));
1409 proto_tree_add_uint(mpls_tree, hf_icmp_mpls_version, tvb, offset, 1, version);
1412 reserved = tvb_get_ntohs(tvb, offset) & 0x0fff;
1413 proto_tree_add_uint_format(mpls_tree, hf_icmp_mpls_reserved,
1414 tvb, offset, 2, reserved,
1415 "Reserved: 0x%03x", reserved);
1418 cksum = tvb_get_ntohs(tvb, offset + 2);
1420 computed_cksum = ip_checksum(tvb_get_ptr(tvb, offset, reported_length),
1423 if (computed_cksum == 0)
1425 proto_tree_add_uint_format(mpls_tree, hf_icmp_mpls_checksum, tvb, offset + 2, 2,
1426 cksum, "Checksum: 0x%04x [correct]", cksum);
1430 proto_tree_add_boolean_hidden(mpls_tree, hf_icmp_mpls_checksum_bad, tvb,
1431 offset + 2, 2, TRUE);
1433 proto_tree_add_uint_format(mpls_tree, hf_icmp_mpls_checksum, tvb, offset + 2, 2,
1435 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1436 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1439 if (version != 1 && version != 2)
1441 /* Unsupported version */
1442 proto_item_append_text(ti, " (unsupported version)");
1446 /* Skip the common header */
1449 /* While there is enough room to read an object */
1450 while (tvb_reported_length_remaining(tvb, offset) >= 4 /* Object header */)
1453 obj_length = tvb_get_ntohs(tvb, offset);
1455 obj_trunc_length = min(obj_length, tvb_reported_length_remaining(tvb, offset));
1457 obj_end_offset = offset + obj_trunc_length;
1459 /* Add a subtree for this object (the text will be reset later) */
1460 tf_object = proto_tree_add_text(mpls_tree, tvb, offset,
1461 max(obj_trunc_length, 4),
1464 mpls_object_tree = proto_item_add_subtree(tf_object, ett_icmp_mpls_object);
1466 proto_tree_add_uint(mpls_object_tree, hf_icmp_mpls_length, tvb, offset, 2, obj_length);
1469 class_num = tvb_get_guint8(tvb, offset + 2);
1470 proto_tree_add_uint(mpls_object_tree, hf_icmp_mpls_class, tvb, offset + 2, 1, class_num);
1473 c_type = tvb_get_guint8(tvb, offset + 3);
1474 proto_tree_add_uint(mpls_object_tree, hf_icmp_mpls_c_type, tvb, offset + 3, 1, c_type);
1476 if (obj_length < 4 /* Object header */)
1478 /* Thanks doc/README.developer :)) */
1479 proto_item_set_text(tf_object, "Object with bad length");
1483 /* Skip the object header */
1486 /* Default cases will set this flag to TRUE */
1487 unknown_object = FALSE;
1491 case MPLS_STACK_ENTRY_OBJECT_CLASS:
1494 case MPLS_STACK_ENTRY_C_TYPE:
1496 proto_item_set_text(tf_object, "MPLS Stack Entry");
1498 /* For each entry */
1499 while (offset + 4 <= obj_end_offset)
1501 if (tvb_reported_length_remaining(tvb, offset) < 4)
1503 /* Not enough room in the packet ! */
1507 /* Create a subtree for each entry (the text will be set later) */
1508 tf_entry = proto_tree_add_text(mpls_object_tree,
1509 tvb, offset, 4, " ");
1510 mpls_stack_object_tree = proto_item_add_subtree(tf_entry,
1511 ett_icmp_mpls_stack_object);
1514 label = (guint)tvb_get_ntohs(tvb, offset);
1515 tmp = tvb_get_guint8(tvb, offset + 2);
1516 label = (label << 4) + (tmp >> 4);
1518 proto_tree_add_uint(mpls_stack_object_tree,
1525 proto_item_set_text(tf_entry, "Label: %u", label);
1527 /* Experimental field (also called "CoS") */
1528 proto_tree_add_uint(mpls_stack_object_tree,
1535 proto_item_append_text(tf_entry, ", Exp: %u", (tmp >> 1) & 0x07);
1538 proto_tree_add_boolean(mpls_stack_object_tree,
1545 proto_item_append_text(tf_entry, ", S: %u", tmp & 0x01);
1548 ttl = tvb_get_guint8(tvb, offset + 3);
1550 proto_tree_add_item(mpls_stack_object_tree,
1557 proto_item_append_text(tf_entry, ", TTL: %u", ttl);
1559 /* Skip the entry */
1564 if (offset < obj_end_offset)
1565 proto_tree_add_text(mpls_object_tree, tvb,
1567 obj_end_offset - offset,
1569 (long)(obj_end_offset - offset));
1574 unknown_object = TRUE;
1577 } /* end switch c_type */
1579 case MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS:
1582 case MPLS_EXTENDED_PAYLOAD_C_TYPE:
1583 proto_item_set_text(tf_object, "Extended Payload");
1585 /* This object contains some portion of the original packet
1586 that could not fit in the 128 bytes of the ICMP payload */
1587 if (obj_trunc_length > 4)
1588 proto_tree_add_text(mpls_object_tree, tvb,
1589 offset, obj_trunc_length - 4,
1590 "Data (%d bytes)", obj_trunc_length - 4);
1595 unknown_object = TRUE;
1598 } /* end switch c_type */
1602 unknown_object = TRUE;
1605 } /* end switch class_num */
1607 /* The switches couldn't decode the object */
1608 if (unknown_object == TRUE)
1610 proto_item_set_text(tf_object, "Unknown object (%d/%d)", class_num, c_type);
1612 if (obj_trunc_length > 4)
1613 proto_tree_add_text(mpls_object_tree, tvb,
1614 offset, obj_trunc_length - 4,
1615 "Data (%d bytes)", obj_trunc_length - 4);
1619 if (obj_trunc_length < obj_length)
1620 proto_item_append_text(tf_object, " (truncated)");
1622 /* Go to the end of the object */
1623 offset = obj_end_offset;
1626 } /* end dissect_mpls_extensions */
1628 static const gchar *unreach_str[] = {"Network unreachable",
1630 "Protocol unreachable",
1632 "Fragmentation needed",
1633 "Source route failed",
1634 "Destination network unknown",
1635 "Destination host unknown",
1636 "Source host isolated",
1637 "Network administratively prohibited",
1638 "Host administratively prohibited",
1639 "Network unreachable for TOS",
1640 "Host unreachable for TOS",
1641 "Communication administratively filtered",
1642 "Host precedence violation",
1643 "Precedence cutoff in effect"};
1645 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1647 static const gchar *redir_str[] = {"Redirect for network",
1648 "Redirect for host",
1649 "Redirect for TOS and network",
1650 "Redirect for TOS and host"};
1652 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1654 static const gchar *ttl_str[] = {"Time to live exceeded in transit",
1655 "Fragment reassembly time exceeded"};
1657 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1659 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1661 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1664 * RFC 792 for basic ICMP.
1665 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1666 * RFC 1256 for router discovery messages.
1667 * RFC 2002 and 3012 for Mobile IP stuff.
1670 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1672 proto_tree *icmp_tree;
1676 guint length, reported_length;
1677 guint16 cksum, computed_cksum;
1678 gchar *type_str, *code_str;
1679 guint8 num_addrs = 0;
1680 guint8 addr_entry_size = 0;
1682 gboolean save_in_error_pkt;
1688 code_str=ep_alloc(64);
1691 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1692 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1693 if (check_col(pinfo->cinfo, COL_INFO))
1694 col_clear(pinfo->cinfo, COL_INFO);
1696 /* To do: check for runts, errs, etc. */
1697 icmp_type = tvb_get_guint8(tvb, 0);
1698 icmp_code = tvb_get_guint8(tvb, 1);
1699 cksum = tvb_get_ntohs(tvb, 2);
1701 switch (icmp_type) {
1702 case ICMP_ECHOREPLY:
1703 type_str="Echo (ping) reply";
1706 type_str="Destination unreachable";
1707 if (icmp_code < N_UNREACH) {
1708 g_snprintf(code_str, 64, "(%s)", unreach_str[icmp_code]);
1710 g_snprintf(code_str, 64, "(Unknown - error?)");
1713 case ICMP_SOURCEQUENCH:
1714 type_str="Source quench (flow control)";
1717 type_str="Redirect";
1718 if (icmp_code < N_REDIRECT) {
1719 g_snprintf(code_str, 64, "(%s)", redir_str[icmp_code]);
1721 g_snprintf(code_str, 64, "(Unknown - error?)");
1725 type_str="Echo (ping) request";
1727 case ICMP_RTRADVERT:
1728 switch (icmp_code) {
1729 case 0: /* Mobile-Ip */
1730 case 16: /* Mobile-Ip */
1731 type_str="Mobile IP Advertisement";
1734 type_str="Router advertisement";
1736 } /* switch icmp_code */
1738 case ICMP_RTRSOLICIT:
1739 type_str="Router solicitation";
1742 type_str="Time-to-live exceeded";
1743 if (icmp_code < N_TIMXCEED) {
1744 g_snprintf(code_str, 64, "(%s)", ttl_str[icmp_code]);
1746 g_snprintf(code_str, 64, "(Unknown - error?)");
1749 case ICMP_PARAMPROB:
1750 type_str="Parameter problem";
1751 if (icmp_code < N_PARAMPROB) {
1752 g_snprintf(code_str, 64, "(%s)", par_str[icmp_code]);
1754 g_snprintf(code_str, 64, "(Unknown - error?)");
1758 type_str="Timestamp request";
1760 case ICMP_TSTAMPREPLY:
1761 type_str="Timestamp reply";
1764 type_str="Information request";
1766 case ICMP_IREQREPLY:
1767 type_str="Information reply";
1770 type_str="Address mask request";
1772 case ICMP_MASKREPLY:
1773 type_str="Address mask reply";
1776 type_str="Unknown ICMP (obsolete or malformed?)";
1780 if (check_col(pinfo->cinfo, COL_INFO)) {
1781 col_add_str(pinfo->cinfo, COL_INFO, type_str);
1782 if (code_str[0] != '\0')
1783 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", code_str);
1787 length = tvb_length(tvb);
1788 reported_length = tvb_reported_length(tvb);
1789 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1790 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1791 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1794 icmp_type, type_str);
1795 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1798 icmp_code, code_str);
1800 if (!pinfo->fragmented && length >= reported_length) {
1801 /* The packet isn't part of a fragmented datagram and isn't
1802 truncated, so we can checksum it. */
1804 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1806 if (computed_cksum == 0) {
1807 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1809 "Checksum: 0x%04x [correct]", cksum);
1811 item = proto_tree_add_boolean(icmp_tree, hf_icmp_checksum_bad,
1813 PROTO_ITEM_SET_HIDDEN(item);
1814 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1816 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1817 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1820 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1823 /* Decode the second 4 bytes of the packet. */
1824 switch (icmp_type) {
1825 case ICMP_ECHOREPLY:
1828 case ICMP_TSTAMPREPLY:
1830 case ICMP_IREQREPLY:
1832 case ICMP_MASKREPLY:
1833 proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, FALSE);
1834 proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2, FALSE);
1838 switch (icmp_code) {
1839 case ICMP_FRAG_NEEDED:
1840 proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6, 2, FALSE);
1845 case ICMP_RTRADVERT:
1846 num_addrs = tvb_get_guint8(tvb, 4);
1847 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1849 addr_entry_size = tvb_get_guint8(tvb, 5);
1850 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1852 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1853 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1856 case ICMP_PARAMPROB:
1857 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1858 tvb_get_guint8(tvb, 4));
1862 proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4, FALSE);
1866 /* Decode the additional information in the packet. */
1867 switch (icmp_type) {
1870 case ICMP_PARAMPROB:
1871 case ICMP_SOURCEQUENCH:
1873 /* Save the current value of the "we're inside an error packet"
1874 flag, and set that flag; subdissectors may treat packets
1875 that are the payload of error packets differently from
1877 save_in_error_pkt = pinfo->in_error_pkt;
1878 pinfo->in_error_pkt = TRUE;
1880 /* Decode the IP header and first 64 bits of data from the
1881 original datagram. */
1882 next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1884 /* There is a collision between RFC 1812 and draft-ietf-mpls-icmp-02.
1885 We don't know how to decode the 128th and following bytes of the ICMP payload.
1886 According to draft-ietf-mpls-icmp-02, these bytes should be decoded as MPLS extensions
1887 whereas RFC 1812 tells us to decode them as a portion of the original packet.
1888 Let the user decide.
1890 Here the user decided to favor MPLS extensions.
1891 Force the IP dissector to decode only the first 128 bytes. */
1892 if ((tvb_reported_length(tvb) > 8 + 128) &&
1893 favor_icmp_mpls_ext && (tvb_get_ntohs(tvb, 8 + 2) > 128))
1894 set_actual_length(next_tvb, 128);
1896 call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1898 /* Restore the "we're inside an error packet" flag. */
1899 pinfo->in_error_pkt = save_in_error_pkt;
1901 /* Decode MPLS extensions if the payload has at least 128 bytes, and
1902 - the original packet in the ICMP payload has less than 128 bytes, or
1903 - the user favors the MPLS extensions analysis */
1904 if ((tvb_reported_length(tvb) > 8 + 128)
1905 && (tvb_get_ntohs(tvb, 8 + 2) <= 128 || favor_icmp_mpls_ext))
1906 dissect_mpls_extensions(tvb, 8 + 128, icmp_tree);
1910 case ICMP_ECHOREPLY:
1912 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1916 case ICMP_RTRADVERT:
1917 if (addr_entry_size == 2) {
1918 for (i = 0; i < num_addrs; i++) {
1919 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1920 "Router address: %s",
1921 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1922 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1923 "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1925 if ((icmp_code == 0) || (icmp_code == 16)) {
1927 dissect_mip_extensions(tvb, 8 + i*8, icmp_tree);
1930 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1935 case ICMP_TSTAMPREPLY:
1936 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %s after midnight UTC",
1937 time_msecs_to_str(tvb_get_ntohl(tvb, 8)));
1938 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %s after midnight UTC",
1939 time_msecs_to_str(tvb_get_ntohl(tvb, 12)));
1940 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %s after midnight UTC",
1941 time_msecs_to_str(tvb_get_ntohl(tvb, 16)));
1945 case ICMP_MASKREPLY:
1946 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1947 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1954 proto_register_ip(void)
1956 static hf_register_info hf[] = {
1959 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1963 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1967 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1970 { &hf_ip_dsfield_dscp,
1971 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1972 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1975 { &hf_ip_dsfield_ect,
1976 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1980 { &hf_ip_dsfield_ce,
1981 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1986 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1989 { &hf_ip_tos_precedence,
1990 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1995 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1999 { &hf_ip_tos_throughput,
2000 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
2004 { &hf_ip_tos_reliability,
2005 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
2010 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
2015 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
2019 { "Identification", "ip.id", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2023 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
2027 { "Destination Host", "ip.dst_host", FT_STRING, BASE_NONE, NULL, 0x0,
2031 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
2035 { "Source Host", "ip.src_host", FT_STRING, BASE_NONE, NULL, 0x0,
2039 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
2043 { "Source or Destination Host", "ip.host", FT_STRING, BASE_NONE, NULL, 0x0,
2047 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
2051 { "Reserved bit", "ip.flags.rb", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_RF >> 12,
2055 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF >> 12,
2059 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF >> 12,
2062 { &hf_ip_frag_offset,
2063 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
2067 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
2071 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
2075 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
2078 { &hf_ip_checksum_good,
2079 { "Good", "ip.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2080 "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
2082 { &hf_ip_checksum_bad,
2083 { "Bad ", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2084 "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
2086 { &hf_ip_fragment_overlap,
2087 { "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2088 "Fragment overlaps with other fragments", HFILL }},
2090 { &hf_ip_fragment_overlap_conflict,
2091 { "Conflicting data in fragment overlap", "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2092 "Overlapping fragments contained conflicting data", HFILL }},
2094 { &hf_ip_fragment_multiple_tails,
2095 { "Multiple tail fragments found", "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2096 "Several tails were found when defragmenting the packet", HFILL }},
2098 { &hf_ip_fragment_too_long_fragment,
2099 { "Fragment too long", "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2100 "Fragment contained data past end of packet", HFILL }},
2102 { &hf_ip_fragment_error,
2103 { "Defragmentation error", "ip.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2104 "Defragmentation error due to illegal fragments", HFILL }},
2107 { "IP Fragment", "ip.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2108 "IP Fragment", HFILL }},
2111 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2112 "IP Fragments", HFILL }},
2114 { &hf_ip_reassembled_in,
2115 { "Reassembled IP in frame", "ip.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2116 "This IP packet is reassembled in this frame", HFILL }}
2118 static gint *ett[] = {
2125 &ett_ip_option_route,
2126 &ett_ip_option_timestamp,
2131 module_t *ip_module;
2133 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
2134 proto_register_field_array(proto_ip, hf, array_length(hf));
2135 proto_register_subtree_array(ett, array_length(ett));
2137 /* subdissector code */
2138 ip_dissector_table = register_dissector_table("ip.proto",
2139 "IP protocol", FT_UINT8, BASE_DEC);
2141 /* Register configuration options */
2142 ip_module = prefs_register_protocol(proto_ip, NULL);
2143 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
2144 "Decode IPv4 TOS field as DiffServ field",
2145 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field (see RFC2474/RFC2475)",
2147 prefs_register_bool_preference(ip_module, "defragment",
2148 "Reassemble fragmented IP datagrams",
2149 "Whether fragmented IP datagrams should be reassembled",
2151 prefs_register_bool_preference(ip_module, "summary_in_tree",
2152 "Show IP summary in protocol tree",
2153 "Whether the IP summary line should be shown in the protocol tree",
2154 &ip_summary_in_tree);
2155 prefs_register_bool_preference(ip_module, "check_checksum" ,
2156 "Validate the IP checksum if possible",
2157 "Whether to validate the IP checksum",
2158 &ip_check_checksum);
2160 register_dissector("ip", dissect_ip, proto_ip);
2161 register_init_routine(ip_defragment_init);
2162 ip_tap=register_tap("ip");
2166 proto_reg_handoff_ip(void)
2168 dissector_handle_t ip_handle;
2170 data_handle = find_dissector("data");
2171 ip_handle = find_dissector("ip");
2172 dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
2173 dissector_add("ppp.protocol", PPP_IP, ip_handle);
2174 dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
2175 dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
2176 dissector_add("gre.proto", GRE_WCCP, ip_handle);
2177 dissector_add("llc.dsap", SAP_IP, ip_handle);
2178 dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
2179 dissector_add("null.type", BSD_AF_INET, ip_handle);
2180 dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
2181 dissector_add("osinl.excl", NLPID_IP, ip_handle);
2182 dissector_add("fr.ietf", NLPID_IP, ip_handle);
2183 dissector_add("x.25.spi", NLPID_IP, ip_handle);
2184 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1051, ip_handle);
2185 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1201, ip_handle);
2186 dissector_add_handle("udp.port", ip_handle);
2190 proto_register_icmp(void)
2192 static hf_register_info hf[] = {
2195 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
2199 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
2202 { &hf_icmp_checksum,
2203 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
2206 { &hf_icmp_checksum_bad,
2207 { "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2211 {"Identifier", "icmp.ident", FT_UINT16, BASE_HEX, NULL, 0x0,
2215 {"Sequence number", "icmp.seq", FT_UINT16, BASE_HEX, NULL, 0x0,
2219 {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL, 0x0,
2222 { &hf_icmp_redir_gw,
2223 {"Gateway address", "icmp.redir_gw", FT_IPv4, BASE_NONE, NULL, 0x0,
2226 { &hf_icmp_mip_type,
2227 { "Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
2228 VALS(mip_extensions), 0x0,"", HFILL}},
2230 { &hf_icmp_mip_length,
2231 { "Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL, 0x0,
2234 { &hf_icmp_mip_prefix_length,
2235 { "Prefix Length", "icmp.mip.prefixlength", FT_UINT8, BASE_DEC, NULL, 0x0,
2239 { "Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC, NULL, 0x0,
2242 { &hf_icmp_mip_life,
2243 { "Registration Lifetime", "icmp.mip.life", FT_UINT16, BASE_DEC, NULL, 0x0,
2246 { &hf_icmp_mip_flags,
2247 { "Flags", "icmp.mip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
2251 { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
2252 "Registration with this FA is required", HFILL }},
2255 { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
2256 "This FA will not accept requests at this time", HFILL }},
2259 { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
2260 "Home Agent Services Offered", HFILL }},
2263 { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
2264 "Foreign Agent Services Offered", HFILL }},
2267 { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
2268 "Minimal encapsulation tunneled datagram support", HFILL }},
2271 { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
2272 "GRE encapsulated tunneled datagram support", HFILL }},
2275 { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
2276 "Van Jacobson Header Compression Support", HFILL }},
2279 { "Reverse tunneling", "icmp.mip.rt", FT_BOOLEAN, 8, NULL, 1,
2280 "Reverse tunneling support", HFILL }},
2283 { &hf_icmp_mip_reserved,
2284 { "Reserved", "icmp.mip.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
2288 { "Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE, NULL, 0x0,
2291 { &hf_icmp_mip_challenge,
2292 { "Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE, NULL, 0x0,
2296 { "ICMP Extensions for MPLS", "icmp.mpls", FT_NONE, BASE_NONE, NULL, 0x0,
2299 { &hf_icmp_mpls_version,
2300 { "Version", "icmp.mpls.version", FT_UINT8, BASE_DEC, NULL, 0x0,
2303 { &hf_icmp_mpls_reserved,
2304 { "Reserved", "icmp.mpls.res", FT_UINT16, BASE_HEX, NULL, 0x0,
2307 { &hf_icmp_mpls_checksum,
2308 { "Checksum", "icmp.mpls.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
2311 { &hf_icmp_mpls_checksum_bad,
2312 { "Bad Checksum", "icmp.mpls.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2315 { &hf_icmp_mpls_length,
2316 { "Length", "icmp.mpls.length", FT_UINT16, BASE_HEX, NULL, 0x0,
2319 { &hf_icmp_mpls_class,
2320 { "Class", "icmp.mpls.class", FT_UINT8, BASE_DEC, NULL, 0x0,
2323 { &hf_icmp_mpls_c_type,
2324 { "C-Type", "icmp.mpls.ctype", FT_UINT8, BASE_DEC, NULL, 0x0,
2327 { &hf_icmp_mpls_label,
2328 { "Label", "icmp.mpls.label", FT_UINT24, BASE_DEC, NULL, 0x00fffff0,
2331 { &hf_icmp_mpls_exp,
2332 { "Experimental", "icmp.mpls.exp", FT_UINT24, BASE_DEC,
2337 { "Stack bit", "icmp.mpls.s", FT_BOOLEAN, 24, TFS(&flags_set_truth), 0x01,
2340 { &hf_icmp_mpls_ttl,
2341 { "Time to live", "icmp.mpls.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
2345 static gint *ett[] = {
2348 &ett_icmp_mip_flags,
2349 /* MPLS extensions */
2351 &ett_icmp_mpls_object,
2352 &ett_icmp_mpls_stack_object
2355 module_t *icmp_module;
2357 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
2359 proto_register_field_array(proto_icmp, hf, array_length(hf));
2360 proto_register_subtree_array(ett, array_length(ett));
2362 icmp_module = prefs_register_protocol(proto_icmp, NULL);
2364 prefs_register_bool_preference(icmp_module, "favor_icmp_mpls",
2365 "Favor ICMP extensions for MPLS",
2366 "Whether the 128th and following bytes of the ICMP payload should be decoded as MPLS extensions or as a portion of the original packet",
2367 &favor_icmp_mpls_ext);
2371 proto_reg_handoff_icmp(void)
2373 dissector_handle_t icmp_handle;
2376 * Get handle for the IP dissector.
2378 ip_handle = find_dissector("ip");
2379 ipv6_handle = find_dissector("ipv6");
2381 icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
2382 dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);