2 * Routines for IP and miscellaneous IP protocol packet disassembly
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
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>
58 static int ip_tap = -1;
60 static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
62 /* Decode the old IPv4 TOS field as the DiffServ DS Field (RFC2474/2475) */
63 static gboolean g_ip_dscp_actif = TRUE;
65 /* Defragment fragmented IP datagrams */
66 static gboolean ip_defragment = TRUE;
68 /* Place IP summary in proto tree */
69 static gboolean ip_summary_in_tree = TRUE;
71 /* Decode the end of the ICMP payload as ICMP MPLS extensions
72 if the packet in the payload has more than 128 bytes */
73 static gboolean favor_icmp_mpls_ext = FALSE;
75 /* Perform IP checksum */
76 static gboolean ip_check_checksum = TRUE;
78 static int proto_ip = -1;
79 static int hf_ip_version = -1;
80 static int hf_ip_hdr_len = -1;
81 static int hf_ip_dsfield = -1;
82 static int hf_ip_dsfield_dscp = -1;
83 static int hf_ip_dsfield_ect = -1;
84 static int hf_ip_dsfield_ce = -1;
85 static int hf_ip_tos = -1;
86 static int hf_ip_tos_precedence = -1;
87 static int hf_ip_tos_delay = -1;
88 static int hf_ip_tos_throughput = -1;
89 static int hf_ip_tos_reliability = -1;
90 static int hf_ip_tos_cost = -1;
91 static int hf_ip_len = -1;
92 static int hf_ip_id = -1;
93 static int hf_ip_dst = -1;
94 static int hf_ip_dst_host = -1;
95 static int hf_ip_src = -1;
96 static int hf_ip_src_host = -1;
97 static int hf_ip_addr = -1;
98 static int hf_ip_host = -1;
99 static int hf_ip_flags = -1;
100 static int hf_ip_flags_rf = -1;
101 static int hf_ip_flags_df = -1;
102 static int hf_ip_flags_mf = -1;
103 static int hf_ip_frag_offset = -1;
104 static int hf_ip_ttl = -1;
105 static int hf_ip_proto = -1;
106 static int hf_ip_checksum = -1;
107 static int hf_ip_checksum_good = -1;
108 static int hf_ip_checksum_bad = -1;
109 static int hf_ip_fragments = -1;
110 static int hf_ip_fragment = -1;
111 static int hf_ip_fragment_overlap = -1;
112 static int hf_ip_fragment_overlap_conflict = -1;
113 static int hf_ip_fragment_multiple_tails = -1;
114 static int hf_ip_fragment_too_long_fragment = -1;
115 static int hf_ip_fragment_error = -1;
116 static int hf_ip_reassembled_in = -1;
118 static gint ett_ip = -1;
119 static gint ett_ip_dsfield = -1;
120 static gint ett_ip_tos = -1;
121 static gint ett_ip_off = -1;
122 static gint ett_ip_options = -1;
123 static gint ett_ip_option_sec = -1;
124 static gint ett_ip_option_route = -1;
125 static gint ett_ip_option_timestamp = -1;
126 static gint ett_ip_fragments = -1;
127 static gint ett_ip_fragment = -1;
128 static gint ett_ip_checksum = -1;
130 static const fragment_items ip_frag_items = {
135 &hf_ip_fragment_overlap,
136 &hf_ip_fragment_overlap_conflict,
137 &hf_ip_fragment_multiple_tails,
138 &hf_ip_fragment_too_long_fragment,
139 &hf_ip_fragment_error,
140 &hf_ip_reassembled_in,
144 static dissector_table_t ip_dissector_table;
146 static dissector_handle_t ip_handle;
147 static dissector_handle_t data_handle;
149 static int proto_icmp = -1;
150 static int hf_icmp_type = -1;
151 static int hf_icmp_code = -1;
152 static int hf_icmp_checksum = -1;
153 static int hf_icmp_checksum_bad = -1;
154 static int hf_icmp_ident = -1;
155 static int hf_icmp_seq_num = -1;
156 static int hf_icmp_mtu = -1;
157 static int hf_icmp_redir_gw = -1;
161 static int hf_icmp_mip_type = -1;
162 static int hf_icmp_mip_length = -1;
163 static int hf_icmp_mip_prefix_length = -1;
164 static int hf_icmp_mip_seq = -1;
165 static int hf_icmp_mip_life = -1;
166 static int hf_icmp_mip_flags = -1;
167 static int hf_icmp_mip_r = -1;
168 static int hf_icmp_mip_b = -1;
169 static int hf_icmp_mip_h = -1;
170 static int hf_icmp_mip_f = -1;
171 static int hf_icmp_mip_m = -1;
172 static int hf_icmp_mip_g = -1;
173 static int hf_icmp_mip_v = -1;
174 static int hf_icmp_mip_res = -1;
175 static int hf_icmp_mip_reserved = -1;
176 static int hf_icmp_mip_coa = -1;
177 static int hf_icmp_mip_challenge = -1;
179 /* MPLS extensions */
180 static int hf_icmp_mpls = -1;
181 static int hf_icmp_mpls_version = -1;
182 static int hf_icmp_mpls_reserved = -1;
183 static int hf_icmp_mpls_checksum = -1;
184 static int hf_icmp_mpls_checksum_bad = -1;
185 static int hf_icmp_mpls_length = -1;
186 static int hf_icmp_mpls_class = -1;
187 static int hf_icmp_mpls_c_type = -1;
188 static int hf_icmp_mpls_label = -1;
189 static int hf_icmp_mpls_exp = -1;
190 static int hf_icmp_mpls_s = -1;
191 static int hf_icmp_mpls_ttl = -1;
193 static gint ett_icmp = -1;
194 static gint ett_icmp_mip = -1;
195 static gint ett_icmp_mip_flags = -1;
196 /* MPLS extensions */
197 static gint ett_icmp_mpls = -1;
198 static gint ett_icmp_mpls_object = -1;
199 static gint ett_icmp_mpls_stack_object = -1;
201 /* ICMP definitions */
203 #define ICMP_ECHOREPLY 0
204 #define ICMP_UNREACH 3
205 #define ICMP_SOURCEQUENCH 4
206 #define ICMP_REDIRECT 5
208 #define ICMP_RTRADVERT 9
209 #define ICMP_RTRSOLICIT 10
210 #define ICMP_TIMXCEED 11
211 #define ICMP_PARAMPROB 12
212 #define ICMP_TSTAMP 13
213 #define ICMP_TSTAMPREPLY 14
215 #define ICMP_IREQREPLY 16
216 #define ICMP_MASKREQ 17
217 #define ICMP_MASKREPLY 18
219 /* ICMP UNREACHABLE */
221 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
222 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
223 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
224 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
225 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
226 #define ICMP_SR_FAILED 5 /* Source Route failed */
227 #define ICMP_NET_UNKNOWN 6
228 #define ICMP_HOST_UNKNOWN 7
229 #define ICMP_HOST_ISOLATED 8
230 #define ICMP_NET_ANO 9
231 #define ICMP_HOST_ANO 10
232 #define ICMP_NET_UNR_TOS 11
233 #define ICMP_HOST_UNR_TOS 12
234 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
235 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
236 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
239 /* IP structs and definitions */
241 /* Offsets of fields within an IP header. */
253 /* Minimum IP header length. */
254 #define IPH_MIN_LEN 20
257 #define IP_RF 0x8000 /* Flag: "Reserved bit" */
258 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
259 #define IP_MF 0x2000 /* Flag: "More Fragments" */
260 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
262 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
263 #define IPDSFIELD_DSCP_MASK 0xFC
264 #define IPDSFIELD_ECN_MASK 0x03
265 #define IPDSFIELD_DSCP_SHIFT 2
266 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
267 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
268 #define IPDSFIELD_DSCP_DEFAULT 0x00
269 #define IPDSFIELD_DSCP_CS1 0x08
270 #define IPDSFIELD_DSCP_CS2 0x10
271 #define IPDSFIELD_DSCP_CS3 0x18
272 #define IPDSFIELD_DSCP_CS4 0x20
273 #define IPDSFIELD_DSCP_CS5 0x28
274 #define IPDSFIELD_DSCP_CS6 0x30
275 #define IPDSFIELD_DSCP_CS7 0x38
276 #define IPDSFIELD_DSCP_AF11 0x0A
277 #define IPDSFIELD_DSCP_AF12 0x0C
278 #define IPDSFIELD_DSCP_AF13 0x0E
279 #define IPDSFIELD_DSCP_AF21 0x12
280 #define IPDSFIELD_DSCP_AF22 0x14
281 #define IPDSFIELD_DSCP_AF23 0x16
282 #define IPDSFIELD_DSCP_AF31 0x1A
283 #define IPDSFIELD_DSCP_AF32 0x1C
284 #define IPDSFIELD_DSCP_AF33 0x1E
285 #define IPDSFIELD_DSCP_AF41 0x22
286 #define IPDSFIELD_DSCP_AF42 0x24
287 #define IPDSFIELD_DSCP_AF43 0x26
288 #define IPDSFIELD_DSCP_EF 0x2E
289 #define IPDSFIELD_ECT_MASK 0x02
290 #define IPDSFIELD_CE_MASK 0x01
292 /* IP TOS, superseded by the DS Field, RFC 2474. */
293 #define IPTOS_TOS_MASK 0x1E
294 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
295 #define IPTOS_NONE 0x00
296 #define IPTOS_LOWCOST 0x02
297 #define IPTOS_RELIABILITY 0x04
298 #define IPTOS_THROUGHPUT 0x08
299 #define IPTOS_LOWDELAY 0x10
300 #define IPTOS_SECURITY 0x1E
302 #define IPTOS_PREC_MASK 0xE0
303 #define IPTOS_PREC_SHIFT 5
304 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
305 #define IPTOS_PREC_NETCONTROL 7
306 #define IPTOS_PREC_INTERNETCONTROL 6
307 #define IPTOS_PREC_CRITIC_ECP 5
308 #define IPTOS_PREC_FLASHOVERRIDE 4
309 #define IPTOS_PREC_FLASH 3
310 #define IPTOS_PREC_IMMEDIATE 2
311 #define IPTOS_PREC_PRIORITY 1
312 #define IPTOS_PREC_ROUTINE 0
315 #define IPOPT_COPY 0x80
317 #define IPOPT_CONTROL 0x00
318 #define IPOPT_RESERVED1 0x20
319 #define IPOPT_MEASUREMENT 0x40
320 #define IPOPT_RESERVED2 0x60
322 #define IPOPT_END (0 |IPOPT_CONTROL)
323 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
324 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
325 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
326 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
327 #define IPOPT_RR (7 |IPOPT_CONTROL)
328 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
329 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
330 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
332 /* IP option lengths */
333 #define IPOLEN_SEC 11
334 #define IPOLEN_LSRR_MIN 3
335 #define IPOLEN_TIMESTAMP_MIN 5
336 #define IPOLEN_RR_MIN 3
338 #define IPOLEN_SSRR_MIN 3
341 #define IPSEC_UNCLASSIFIED 0x0000
342 #define IPSEC_CONFIDENTIAL 0xF135
343 #define IPSEC_EFTO 0x789A
344 #define IPSEC_MMMM 0xBC4D
345 #define IPSEC_RESTRICTED 0xAF13
346 #define IPSEC_SECRET 0xD788
347 #define IPSEC_TOPSECRET 0x6BC5
348 #define IPSEC_RESERVED1 0x35E2
349 #define IPSEC_RESERVED2 0x9AF1
350 #define IPSEC_RESERVED3 0x4D78
351 #define IPSEC_RESERVED4 0x24BD
352 #define IPSEC_RESERVED5 0x135E
353 #define IPSEC_RESERVED6 0x89AF
354 #define IPSEC_RESERVED7 0xC4D6
355 #define IPSEC_RESERVED8 0xE26B
357 #define IPOPT_TS_TSONLY 0 /* timestamps only */
358 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
359 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
362 * defragmentation of IPv4
364 static GHashTable *ip_fragment_table = NULL;
365 static GHashTable *ip_reassembled_table = NULL;
368 ip_defragment_init(void)
370 fragment_table_init(&ip_fragment_table);
371 reassembled_table_init(&ip_reassembled_table);
375 capture_ip(const guchar *pd, int offset, int len, packet_counts *ld) {
376 if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
380 switch (pd[offset + 9]) {
388 case IP_PROTO_ICMPV6: /* XXX - separate counters? */
409 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
410 guint optlen, packet_info *pinfo _U_,
411 proto_tree *opt_tree)
413 proto_tree *field_tree = NULL;
416 static const value_string secl_vals[] = {
417 {IPSEC_UNCLASSIFIED, "Unclassified"},
418 {IPSEC_CONFIDENTIAL, "Confidential"},
419 {IPSEC_EFTO, "EFTO" },
420 {IPSEC_MMMM, "MMMM" },
421 {IPSEC_RESTRICTED, "Restricted" },
422 {IPSEC_SECRET, "Secret" },
423 {IPSEC_TOPSECRET, "Top secret" },
424 {IPSEC_RESERVED1, "Reserved" },
425 {IPSEC_RESERVED2, "Reserved" },
426 {IPSEC_RESERVED3, "Reserved" },
427 {IPSEC_RESERVED4, "Reserved" },
428 {IPSEC_RESERVED5, "Reserved" },
429 {IPSEC_RESERVED6, "Reserved" },
430 {IPSEC_RESERVED7, "Reserved" },
431 {IPSEC_RESERVED8, "Reserved" },
434 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
435 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
438 val = tvb_get_ntohs(tvb, offset);
439 proto_tree_add_text(field_tree, tvb, offset, 2,
440 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
443 val = tvb_get_ntohs(tvb, offset);
444 proto_tree_add_text(field_tree, tvb, offset, 2,
445 "Compartments: %u", val);
448 proto_tree_add_text(field_tree, tvb, offset, 2,
449 "Handling restrictions: %c%c",
450 tvb_get_guint8(tvb, offset),
451 tvb_get_guint8(tvb, offset + 1));
454 proto_tree_add_text(field_tree, tvb, offset, 3,
455 "Transmission control code: %c%c%c",
456 tvb_get_guint8(tvb, offset),
457 tvb_get_guint8(tvb, offset + 1),
458 tvb_get_guint8(tvb, offset + 2));
462 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
463 guint optlen, packet_info *pinfo _U_,
464 proto_tree *opt_tree)
466 proto_tree *field_tree = NULL;
472 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
474 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
476 optoffset += 2; /* skip past type and length */
477 optlen -= 2; /* subtract size of type and length */
479 ptr = tvb_get_guint8(tvb, offset + optoffset);
480 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
481 "Pointer: %d%s", ptr,
482 ((ptr < 4) ? " (points before first address)" :
483 ((ptr & 3) ? " (points to middle of address)" : "")));
486 ptr--; /* ptr is 1-origin */
490 proto_tree_add_text(field_tree, tvb, offset, optlen,
491 "(suboption would go past end of option)");
495 addr = tvb_get_ipv4(tvb, offset + optoffset);
496 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
498 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
499 ((optoffset == ptr) ? " <- (current)" : ""));
506 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
507 guint optlen, packet_info *pinfo _U_,
508 proto_tree *opt_tree)
510 proto_tree_add_text(opt_tree, tvb, offset, optlen,
511 "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
516 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
517 int offset, guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
519 proto_tree *field_tree = NULL;
524 static const value_string flag_vals[] = {
525 {IPOPT_TS_TSONLY, "Time stamps only" },
526 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
527 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
532 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
533 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
535 optoffset += 2; /* skip past type and length */
536 optlen -= 2; /* subtract size of type and length */
538 ptr = tvb_get_guint8(tvb, offset + optoffset);
539 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
540 "Pointer: %d%s", ptr,
541 ((ptr < 5) ? " (points before first address)" :
542 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
545 ptr--; /* ptr is 1-origin */
547 flg = tvb_get_guint8(tvb, offset + optoffset);
548 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
549 "Overflow: %u", flg >> 4);
551 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
552 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
557 if (flg == IPOPT_TS_TSANDADDR) {
559 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
560 "(suboption would go past end of option)");
563 addr = tvb_get_ipv4(tvb, offset + optoffset);
564 ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
566 proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
567 "Address = %s, time stamp = %u",
568 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
573 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
574 "(suboption would go past end of option)");
577 ts = tvb_get_ntohl(tvb, offset + optoffset);
579 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
580 "Time stamp = %u", ts);
587 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
588 guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
590 /* Router-Alert, as defined by RFC2113 */
591 int opt = tvb_get_ntohs(tvb, offset + 2);
592 static const value_string ra_opts[] = {
593 {0, "Every router examines packet"},
597 proto_tree_add_text(opt_tree, tvb, offset, optlen,
598 "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
602 static const ip_tcp_opt ipopts[] = {
625 dissect_ipopt_security
629 "Strict source route",
630 &ett_ip_option_route,
637 "Loose source route",
638 &ett_ip_option_route,
646 &ett_ip_option_route,
662 &ett_ip_option_timestamp,
664 IPOLEN_TIMESTAMP_MIN,
665 dissect_ipopt_timestamp
677 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
679 /* Dissect the IP or TCP options in a packet. */
681 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
682 const ip_tcp_opt *opttab, int nopts, int eol,
683 packet_info *pinfo, proto_tree *opt_tree)
686 const ip_tcp_opt *optp;
687 opt_len_type len_type;
690 #define NAME_STR_LEN 7+1+1+2+2+1+1 /* "Unknown (0x%02x)" */
692 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
693 int, guint, packet_info *, proto_tree *);
696 name_str=ep_alloc(NAME_STR_LEN);
698 opt = tvb_get_guint8(tvb, offset);
699 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
700 if (optp->optcode == opt)
703 if (optp == &opttab[nopts]) {
704 /* We assume that the only NO_LENGTH options are EOL and NOP options,
705 so that we can treat unknown options as VARIABLE_LENGTH with a
706 minimum of 2, and at least be able to move on to the next option
707 by using the length in the option. */
708 optp = NULL; /* indicate that we don't know this option */
709 len_type = VARIABLE_LENGTH;
711 g_snprintf(name_str, NAME_STR_LEN, "Unknown (0x%02x)", opt);
715 len_type = optp->len_type;
716 optlen = optp->optlen;
718 dissect = optp->dissect;
720 --length; /* account for type byte */
721 if (len_type != NO_LENGTH) {
722 /* Option has a length. Is it in the packet? */
724 /* Bogus - packet must at least include option code byte and
726 proto_tree_add_text(opt_tree, tvb, offset, 1,
727 "%s (length byte past end of options)", name);
730 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
731 --length; /* account for length byte */
733 /* Bogus - option length is too short to include option code and
735 proto_tree_add_text(opt_tree, tvb, offset, 2,
736 "%s (with too-short option length = %u byte%s)", name,
737 len, plurality(len, "", "s"));
739 } else if (len - 2 > length) {
740 /* Bogus - option goes past the end of the header. */
741 proto_tree_add_text(opt_tree, tvb, offset, length,
742 "%s (option length = %u byte%s says option goes past end of options)",
743 name, len, plurality(len, "", "s"));
745 } else if (len_type == FIXED_LENGTH && len != optlen) {
746 /* Bogus - option length isn't what it's supposed to be for this
748 proto_tree_add_text(opt_tree, tvb, offset, len,
749 "%s (with option length = %u byte%s; should be %u)", name,
750 len, plurality(len, "", "s"), optlen);
752 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
753 /* Bogus - option length is less than what it's supposed to be for
755 proto_tree_add_text(opt_tree, tvb, offset, len,
756 "%s (with option length = %u byte%s; should be >= %u)", name,
757 len, plurality(len, "", "s"), optlen);
761 proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
762 name, len, plurality(len, "", "s"));
764 if (dissect != NULL) {
765 /* Option has a dissector. */
766 (*dissect)(optp, tvb, offset, len, pinfo, opt_tree);
768 /* Option has no data, hence no dissector. */
769 proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
772 len -= 2; /* subtract size of type and length */
777 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
785 const value_string dscp_vals[] = {
786 { IPDSFIELD_DSCP_DEFAULT, "Default" },
787 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
788 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
789 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
790 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
791 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
792 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
793 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
794 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
795 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
796 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
797 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
798 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
799 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
800 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
801 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
802 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
803 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
804 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
805 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
806 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
809 static const value_string precedence_vals[] = {
810 { IPTOS_PREC_ROUTINE, "routine" },
811 { IPTOS_PREC_PRIORITY, "priority" },
812 { IPTOS_PREC_IMMEDIATE, "immediate" },
813 { IPTOS_PREC_FLASH, "flash" },
814 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
815 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
816 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
817 { IPTOS_PREC_NETCONTROL, "network control" },
820 static const value_string iptos_vals[] = {
821 { IPTOS_NONE, "None" },
822 { IPTOS_LOWCOST, "Minimize cost" },
823 { IPTOS_RELIABILITY, "Maximize reliability" },
824 { IPTOS_THROUGHPUT, "Maximize throughput" },
825 { IPTOS_LOWDELAY, "Minimize delay" },
826 { IPTOS_SECURITY, "Maximize security" },
830 static const true_false_string tos_set_low = {
835 static const true_false_string tos_set_high = {
840 static guint16 ip_checksum(const guint8 *ptr, int len)
844 cksum_vec[0].ptr = ptr;
845 cksum_vec[0].len = len;
846 return in_cksum(&cksum_vec[0], 1);
850 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
852 proto_tree *ip_tree = NULL, *field_tree;
853 proto_item *ti = NULL, *tf;
860 fragment_data *ipfd_head=NULL;
862 gboolean update_col_info = TRUE;
863 gboolean save_fragmented;
864 static e_ip eip_arr[4];
865 static int eip_current=0;
867 const guchar *src_addr, *dst_addr;
868 guint32 src32, dst32;
871 proto_tree *checksum_tree;
879 iph=&eip_arr[eip_current];
881 if (check_col(pinfo->cinfo, COL_PROTOCOL))
882 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
883 if (check_col(pinfo->cinfo, COL_INFO))
884 col_clear(pinfo->cinfo, COL_INFO);
886 iph->ip_v_hl = tvb_get_guint8(tvb, offset);
887 hlen = lo_nibble(iph->ip_v_hl) * 4; /* IP header length, in bytes */
890 ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
891 ip_tree = proto_item_add_subtree(ti, ett_ip);
893 proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1,
894 hi_nibble(iph->ip_v_hl));
897 /* if IP is not referenced from any filters we dont need to worry about
898 generating any tree items. We must do this after we created the actual
899 protocol above so that proto hier stat still works though.
901 if(!proto_field_is_referenced(parent_tree, proto_ip)){
905 if (hlen < IPH_MIN_LEN) {
906 if (check_col(pinfo->cinfo, COL_INFO))
907 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
910 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
911 "Header length: %u bytes (bogus, must be at least %u)", hlen,
918 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
919 "Header length: %u bytes", hlen);
922 iph->ip_tos = tvb_get_guint8(tvb, offset + 1);
924 if (g_ip_dscp_actif) {
925 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph->ip_tos,
926 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph->ip_tos,
927 IPDSFIELD_DSCP(iph->ip_tos), val_to_str(IPDSFIELD_DSCP(iph->ip_tos), dscp_vals,
928 "Unknown DSCP"),IPDSFIELD_ECN(iph->ip_tos));
930 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
931 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph->ip_tos);
932 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph->ip_tos);
933 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph->ip_tos);
935 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph->ip_tos,
936 "Type of service: 0x%02x (%s)", iph->ip_tos,
937 val_to_str( IPTOS_TOS(iph->ip_tos), iptos_vals, "Unknown") );
939 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
940 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph->ip_tos);
941 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph->ip_tos);
942 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph->ip_tos);
943 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph->ip_tos);
944 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph->ip_tos);
948 /* Length of IP datagram.
949 XXX - what if this is greater than the reported length of the
950 tvbuff? This could happen, for example, in an IP datagram
951 inside an ICMP datagram; we need to somehow let the
952 dissector we call know that, as it might want to avoid
953 doing its checksumming. */
954 iph->ip_len = tvb_get_ntohs(tvb, offset + 2);
956 /* Adjust the length of this tvbuff to include only the IP datagram. */
957 set_actual_length(tvb, iph->ip_len);
959 if (iph->ip_len < hlen) {
960 if (check_col(pinfo->cinfo, COL_INFO))
961 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP length (%u, less than header length %u)",
964 proto_tree_add_uint_format(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len,
965 "Total length: %u bytes (bogus, less than header length %u)", iph->ip_len,
971 proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len);
973 iph->ip_id = tvb_get_ntohs(tvb, offset + 4);
975 proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph->ip_id);
977 iph->ip_off = tvb_get_ntohs(tvb, offset + 6);
979 flags = (iph->ip_off & (IP_RF | IP_DF | IP_MF)) >> 12;
980 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
981 field_tree = proto_item_add_subtree(tf, ett_ip_off);
982 proto_tree_add_boolean(field_tree, hf_ip_flags_rf, tvb, offset + 6, 1, flags);
983 if (flags & (IP_DF>>12)) proto_item_append_text(tf, " (Don't Fragment)");
984 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags);
985 if (flags & (IP_MF>>12)) proto_item_append_text(tf, " (More Fragments)");
986 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags);
988 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
989 (iph->ip_off & IP_OFFSET)*8);
993 proto_tree_add_item(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, FALSE);
995 iph->ip_p = tvb_get_guint8(tvb, offset + 9);
997 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph->ip_p,
998 "Protocol: %s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
1001 iph->ip_sum = tvb_get_ntohs(tvb, offset + 10);
1004 * If we have the entire IP header available, check the checksum.
1006 if (ip_check_checksum && tvb_bytes_exist(tvb, offset, hlen)) {
1007 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
1010 item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
1011 "Header checksum: 0x%04x [correct]", iph->ip_sum);
1012 checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
1013 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, TRUE);
1014 PROTO_ITEM_SET_GENERATED(item);
1015 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, FALSE);
1016 PROTO_ITEM_SET_GENERATED(item);
1018 item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
1019 "Header checksum: 0x%04x [incorrect, should be 0x%04x]", iph->ip_sum,
1020 in_cksum_shouldbe(iph->ip_sum, ipsum));
1021 checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
1022 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, FALSE);
1023 PROTO_ITEM_SET_GENERATED(item);
1024 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
1025 PROTO_ITEM_SET_GENERATED(item);
1031 item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
1032 "Header checksum: 0x%04x [%s]", iph->ip_sum,
1033 ip_check_checksum ? "not all data available" : "validation disabled");
1034 checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
1035 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, FALSE);
1036 PROTO_ITEM_SET_GENERATED(item);
1037 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, FALSE);
1038 PROTO_ITEM_SET_GENERATED(item);
1041 src_addr = tvb_get_ptr(tvb, offset + IPH_SRC, 4);
1042 src32 = tvb_get_ntohl(tvb, offset + IPH_SRC);
1043 SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, src_addr);
1044 SET_ADDRESS(&pinfo->src, AT_IPv4, 4, src_addr);
1045 SET_ADDRESS(&iph->ip_src, AT_IPv4, 4, src_addr);
1047 memcpy(&addr, iph->ip_src.data, 4);
1048 if (ip_summary_in_tree) {
1049 proto_item_append_text(ti, ", Src: %s (%s)",
1050 get_hostname(addr), ip_to_str(iph->ip_src.data));
1052 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, addr);
1053 item = proto_tree_add_ipv4(ip_tree, hf_ip_addr, tvb, offset + 12, 4, addr);
1054 PROTO_ITEM_SET_HIDDEN(item);
1055 item = proto_tree_add_string(ip_tree, hf_ip_src_host, tvb, offset + 12, 4, get_hostname(addr));
1056 PROTO_ITEM_SET_GENERATED(item);
1057 PROTO_ITEM_SET_HIDDEN(item);
1058 item = proto_tree_add_string(ip_tree, hf_ip_host, tvb, offset + 12, 4, get_hostname(addr));
1059 PROTO_ITEM_SET_GENERATED(item);
1060 PROTO_ITEM_SET_HIDDEN(item);
1062 dst_addr = tvb_get_ptr(tvb, offset + IPH_DST, 4);
1063 dst32 = tvb_get_ntohl(tvb, offset + IPH_DST);
1064 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, dst_addr);
1065 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, dst_addr);
1066 SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, dst_addr);
1069 memcpy(&addr, iph->ip_dst.data, 4);
1070 if (ip_summary_in_tree) {
1071 proto_item_append_text(ti, ", Dst: %s (%s)",
1072 get_hostname(addr), ip_to_str(iph->ip_dst.data));
1074 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, addr);
1075 item = proto_tree_add_ipv4(ip_tree, hf_ip_addr, tvb, offset + 16, 4, addr);
1076 PROTO_ITEM_SET_HIDDEN(item);
1077 item = proto_tree_add_string(ip_tree, hf_ip_dst_host, tvb, offset + 16, 4, get_hostname(addr));
1078 PROTO_ITEM_SET_GENERATED(item);
1079 PROTO_ITEM_SET_HIDDEN(item);
1080 item = proto_tree_add_string(ip_tree, hf_ip_host, tvb, offset + 16, 4, get_hostname(addr));
1081 PROTO_ITEM_SET_GENERATED(item);
1082 PROTO_ITEM_SET_HIDDEN(item);
1086 /* Decode IP options, if any. */
1087 if (hlen > IPH_MIN_LEN) {
1088 /* There's more than just the fixed-length header. Decode the
1090 optlen = hlen - IPH_MIN_LEN; /* length of options, in bytes */
1091 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
1092 "Options: (%u bytes)", optlen);
1093 field_tree = proto_item_add_subtree(tf, ett_ip_options);
1094 dissect_ip_tcp_options(tvb, offset + 20, optlen,
1095 ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
1099 pinfo->ipproto = iph->ip_p;
1101 pinfo->iplen = iph->ip_len;
1103 pinfo->iphdrlen = hlen;
1105 /* Skip over header + options */
1107 nxt = iph->ip_p; /* XXX - what if this isn't the same for all fragments? */
1109 /* If ip_defragment is on, this is a fragment, we have all the data
1110 * in the fragment, and the header checksum is valid, then just add
1111 * the fragment to the hashtable.
1113 save_fragmented = pinfo->fragmented;
1114 if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
1115 tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
1117 ipfd_head = fragment_add_check(tvb, offset, pinfo,
1118 iph->ip_id ^ src32 ^ dst32,
1120 ip_reassembled_table,
1121 (iph->ip_off & IP_OFFSET)*8,
1122 pinfo->iplen - pinfo->iphdrlen,
1123 iph->ip_off & IP_MF);
1125 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv4",
1126 ipfd_head, &ip_frag_items, &update_col_info, ip_tree);
1128 /* If this is the first fragment, dissect its contents, otherwise
1129 just show it as a fragment.
1131 XXX - if we eventually don't save the reassembled contents of all
1132 fragmented datagrams, we may want to always reassemble. */
1133 if (iph->ip_off & IP_OFFSET) {
1134 /* Not the first fragment - don't dissect it. */
1137 /* First fragment, or not fragmented. Dissect what we have here. */
1139 /* Get a tvbuff for the payload. */
1140 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1143 * If this is the first fragment, but not the only fragment,
1144 * tell the next protocol that.
1146 if (iph->ip_off & IP_MF)
1147 pinfo->fragmented = TRUE;
1149 pinfo->fragmented = FALSE;
1153 if (next_tvb == NULL) {
1154 /* Just show this as a fragment. */
1155 if (check_col(pinfo->cinfo, COL_INFO)) {
1156 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1157 ipprotostr(iph->ip_p), iph->ip_p, (iph->ip_off & IP_OFFSET) * 8);
1159 if( ipfd_head && ipfd_head->reassembled_in != pinfo->fd->num ){
1160 if (check_col(pinfo->cinfo, COL_INFO)) {
1161 col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]",
1162 ipfd_head->reassembled_in);
1166 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
1168 pinfo->fragmented = save_fragmented;
1172 /* Hand off to the next protocol.
1174 XXX - setting the columns only after trying various dissectors means
1175 that if one of those dissectors throws an exception, the frame won't
1176 even be labelled as an IP frame; ideally, if a frame being dissected
1177 throws an exception, it'll be labelled as a mangled frame of the
1178 type in question. */
1179 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, parent_tree)) {
1180 /* Unknown protocol */
1181 if (update_col_info) {
1182 if (check_col(pinfo->cinfo, COL_INFO))
1183 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
1185 call_dissector(data_handle,next_tvb, pinfo, parent_tree);
1187 pinfo->fragmented = save_fragmented;
1190 tap_queue_packet(ip_tap, pinfo, iph);
1194 #define ICMP_MIP_EXTENSION_PAD 0
1195 #define ICMP_MIP_MOB_AGENT_ADV 16
1196 #define ICMP_MIP_PREFIX_LENGTHS 19
1197 #define ICMP_MIP_CHALLENGE 24
1199 static value_string mip_extensions[] = {
1200 { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
1201 { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1203 { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
1204 { ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
1209 * Dissect the mobile ip advertisement extensions.
1212 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1218 proto_tree *mip_tree=NULL;
1219 proto_tree *flags_tree=NULL;
1223 /* Not much to do if we're not parsing everything */
1226 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1228 type = tvb_get_guint8(tvb, offset + 0);
1230 length = tvb_get_guint8(tvb, offset + 1);
1234 ti = proto_tree_add_text(tree, tvb, offset,
1235 type?(length + 2):1,
1237 val_to_str(type, mip_extensions,
1239 mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1243 case ICMP_MIP_EXTENSION_PAD:
1244 /* One byte padding extension */
1245 /* Add our fields */
1247 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1251 case ICMP_MIP_MOB_AGENT_ADV:
1252 /* Mobility Agent Advertisement Extension (RFC 2002)*/
1253 /* Add our fields */
1255 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1259 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1262 /* sequence number */
1263 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset,
1266 /* Registration Lifetime */
1267 proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset,
1271 flags = tvb_get_guint8(tvb, offset);
1272 ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1274 flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1275 proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1276 proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1277 proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1278 proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1279 proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1280 proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1281 proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1282 proto_tree_add_boolean(flags_tree, hf_icmp_mip_res, tvb, offset, 1, flags);
1286 proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset,
1291 numCOAs = (length - 6) / 4;
1292 for (i=0; i<numCOAs; i++) {
1293 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset,
1298 case ICMP_MIP_PREFIX_LENGTHS:
1299 /* Prefix-Lengths Extension (RFC 2002)*/
1300 /* Add our fields */
1302 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1306 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1310 /* prefix lengths */
1311 for(i=0; i<length; i++) {
1312 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1317 case ICMP_MIP_CHALLENGE:
1318 /* Challenge Extension (RFC 3012)*/
1320 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1324 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1328 proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset,
1334 g_warning("Unknown type(%u)! I hope the length is right (%u)",
1336 offset += length + 2;
1341 } /* dissect_mip_extensions */
1343 #define MPLS_STACK_ENTRY_OBJECT_CLASS 1
1344 #define MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS 2
1346 #define MPLS_STACK_ENTRY_C_TYPE 1
1347 #define MPLS_EXTENDED_PAYLOAD_C_TYPE 1
1349 /* XXX no header defines these macros ??? */
1351 #define min(a,b) (((a)<(b))?(a):(b))
1355 #define max(a,b) (((a)>(b))?(a):(b))
1359 * Dissect the MPLS extensions
1362 dissect_mpls_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1370 guint16 cksum, computed_cksum;
1371 guint16 obj_length, obj_trunc_length;
1372 proto_item *ti, *tf_object, *tf_entry;
1373 proto_tree *mpls_tree=NULL, *mpls_object_tree, *mpls_stack_object_tree;
1374 guint obj_end_offset;
1375 guint reported_length;
1377 gboolean unknown_object;
1382 reported_length = tvb_reported_length_remaining(tvb, offset);
1384 if (reported_length < 4 /* Common header */)
1386 proto_tree_add_text(tree, tvb, offset,
1388 "MPLS Extensions (truncated)");
1392 /* Add a tree for the MPLS extensions */
1393 ti = proto_tree_add_none_format(tree, hf_icmp_mpls, tvb,
1394 offset, reported_length, "MPLS Extensions");
1396 mpls_tree = proto_item_add_subtree(ti, ett_icmp_mpls);
1399 version = hi_nibble(tvb_get_guint8(tvb, offset));
1400 proto_tree_add_uint(mpls_tree, hf_icmp_mpls_version, tvb, offset, 1, version);
1403 reserved = tvb_get_ntohs(tvb, offset) & 0x0fff;
1404 proto_tree_add_uint_format(mpls_tree, hf_icmp_mpls_reserved,
1405 tvb, offset, 2, reserved,
1406 "Reserved: 0x%03x", reserved);
1409 cksum = tvb_get_ntohs(tvb, offset + 2);
1411 computed_cksum = ip_checksum(tvb_get_ptr(tvb, offset, reported_length),
1414 if (computed_cksum == 0)
1416 proto_tree_add_uint_format(mpls_tree, hf_icmp_mpls_checksum, tvb, offset + 2, 2,
1417 cksum, "Checksum: 0x%04x [correct]", cksum);
1421 proto_tree_add_boolean_hidden(mpls_tree, hf_icmp_mpls_checksum_bad, tvb,
1422 offset + 2, 2, TRUE);
1424 proto_tree_add_uint_format(mpls_tree, hf_icmp_mpls_checksum, tvb, offset + 2, 2,
1426 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1427 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1430 if (version != 1 && version != 2)
1432 /* Unsupported version */
1433 proto_item_append_text(ti, " (unsupported version)");
1437 /* Skip the common header */
1440 /* While there is enough room to read an object */
1441 while (tvb_reported_length_remaining(tvb, offset) >= 4 /* Object header */)
1444 obj_length = tvb_get_ntohs(tvb, offset);
1446 obj_trunc_length = min(obj_length, tvb_reported_length_remaining(tvb, offset));
1448 obj_end_offset = offset + obj_trunc_length;
1450 /* Add a subtree for this object (the text will be reset later) */
1451 tf_object = proto_tree_add_text(mpls_tree, tvb, offset,
1452 max(obj_trunc_length, 4),
1455 mpls_object_tree = proto_item_add_subtree(tf_object, ett_icmp_mpls_object);
1457 proto_tree_add_uint(mpls_object_tree, hf_icmp_mpls_length, tvb, offset, 2, obj_length);
1460 class_num = tvb_get_guint8(tvb, offset + 2);
1461 proto_tree_add_uint(mpls_object_tree, hf_icmp_mpls_class, tvb, offset + 2, 1, class_num);
1464 c_type = tvb_get_guint8(tvb, offset + 3);
1465 proto_tree_add_uint(mpls_object_tree, hf_icmp_mpls_c_type, tvb, offset + 3, 1, c_type);
1467 if (obj_length < 4 /* Object header */)
1469 /* Thanks doc/README.developer :)) */
1470 proto_item_set_text(tf_object, "Object with bad length");
1474 /* Skip the object header */
1477 /* Default cases will set this flag to TRUE */
1478 unknown_object = FALSE;
1482 case MPLS_STACK_ENTRY_OBJECT_CLASS:
1485 case MPLS_STACK_ENTRY_C_TYPE:
1487 proto_item_set_text(tf_object, "MPLS Stack Entry");
1489 /* For each entry */
1490 while (offset + 4 <= obj_end_offset)
1492 if (tvb_reported_length_remaining(tvb, offset) < 4)
1494 /* Not enough room in the packet ! */
1498 /* Create a subtree for each entry (the text will be set later) */
1499 tf_entry = proto_tree_add_text(mpls_object_tree,
1500 tvb, offset, 4, " ");
1501 mpls_stack_object_tree = proto_item_add_subtree(tf_entry,
1502 ett_icmp_mpls_stack_object);
1505 label = (guint)tvb_get_ntohs(tvb, offset);
1506 tmp = tvb_get_guint8(tvb, offset + 2);
1507 label = (label << 4) + (tmp >> 4);
1509 proto_tree_add_uint(mpls_stack_object_tree,
1516 proto_item_set_text(tf_entry, "Label: %u", label);
1518 /* Experimental field (also called "CoS") */
1519 proto_tree_add_uint(mpls_stack_object_tree,
1526 proto_item_append_text(tf_entry, ", Exp: %u", (tmp >> 1) & 0x07);
1529 proto_tree_add_boolean(mpls_stack_object_tree,
1536 proto_item_append_text(tf_entry, ", S: %u", tmp & 0x01);
1539 ttl = tvb_get_guint8(tvb, offset + 3);
1541 proto_tree_add_item(mpls_stack_object_tree,
1548 proto_item_append_text(tf_entry, ", TTL: %u", ttl);
1550 /* Skip the entry */
1555 if (offset < obj_end_offset)
1556 proto_tree_add_text(mpls_object_tree, tvb,
1558 obj_end_offset - offset,
1560 (long)(obj_end_offset - offset));
1565 unknown_object = TRUE;
1568 } /* end switch c_type */
1570 case MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS:
1573 case MPLS_EXTENDED_PAYLOAD_C_TYPE:
1574 proto_item_set_text(tf_object, "Extended Payload");
1576 /* This object contains some portion of the original packet
1577 that could not fit in the 128 bytes of the ICMP payload */
1578 if (obj_trunc_length > 4)
1579 proto_tree_add_text(mpls_object_tree, tvb,
1580 offset, obj_trunc_length - 4,
1581 "Data (%d bytes)", obj_trunc_length - 4);
1586 unknown_object = TRUE;
1589 } /* end switch c_type */
1593 unknown_object = TRUE;
1596 } /* end switch class_num */
1598 /* The switches couldn't decode the object */
1599 if (unknown_object == TRUE)
1601 proto_item_set_text(tf_object, "Unknown object (%d/%d)", class_num, c_type);
1603 if (obj_trunc_length > 4)
1604 proto_tree_add_text(mpls_object_tree, tvb,
1605 offset, obj_trunc_length - 4,
1606 "Data (%d bytes)", obj_trunc_length - 4);
1610 if (obj_trunc_length < obj_length)
1611 proto_item_append_text(tf_object, " (truncated)");
1613 /* Go to the end of the object */
1614 offset = obj_end_offset;
1617 } /* end dissect_mpls_extensions */
1619 static const gchar *unreach_str[] = {"Network unreachable",
1621 "Protocol unreachable",
1623 "Fragmentation needed",
1624 "Source route failed",
1625 "Destination network unknown",
1626 "Destination host unknown",
1627 "Source host isolated",
1628 "Network administratively prohibited",
1629 "Host administratively prohibited",
1630 "Network unreachable for TOS",
1631 "Host unreachable for TOS",
1632 "Communication administratively filtered",
1633 "Host precedence violation",
1634 "Precedence cutoff in effect"};
1636 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1638 static const gchar *redir_str[] = {"Redirect for network",
1639 "Redirect for host",
1640 "Redirect for TOS and network",
1641 "Redirect for TOS and host"};
1643 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1645 static const gchar *ttl_str[] = {"Time to live exceeded in transit",
1646 "Fragment reassembly time exceeded"};
1648 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1650 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1652 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1655 * RFC 792 for basic ICMP.
1656 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1657 * RFC 1256 for router discovery messages.
1658 * RFC 2002 and 3012 for Mobile IP stuff.
1661 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1663 proto_tree *icmp_tree;
1667 guint length, reported_length;
1668 guint16 cksum, computed_cksum;
1669 gchar *type_str, *code_str;
1670 guint8 num_addrs = 0;
1671 guint8 addr_entry_size = 0;
1673 gboolean save_in_error_pkt;
1679 code_str=ep_alloc(64);
1682 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1683 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1684 if (check_col(pinfo->cinfo, COL_INFO))
1685 col_clear(pinfo->cinfo, COL_INFO);
1687 /* To do: check for runts, errs, etc. */
1688 icmp_type = tvb_get_guint8(tvb, 0);
1689 icmp_code = tvb_get_guint8(tvb, 1);
1690 cksum = tvb_get_ntohs(tvb, 2);
1692 switch (icmp_type) {
1693 case ICMP_ECHOREPLY:
1694 type_str="Echo (ping) reply";
1697 type_str="Destination unreachable";
1698 if (icmp_code < N_UNREACH) {
1699 g_snprintf(code_str, 64, "(%s)", unreach_str[icmp_code]);
1701 g_snprintf(code_str, 64, "(Unknown - error?)");
1704 case ICMP_SOURCEQUENCH:
1705 type_str="Source quench (flow control)";
1708 type_str="Redirect";
1709 if (icmp_code < N_REDIRECT) {
1710 g_snprintf(code_str, 64, "(%s)", redir_str[icmp_code]);
1712 g_snprintf(code_str, 64, "(Unknown - error?)");
1716 type_str="Echo (ping) request";
1718 case ICMP_RTRADVERT:
1719 switch (icmp_code) {
1720 case 0: /* Mobile-Ip */
1721 case 16: /* Mobile-Ip */
1722 type_str="Mobile IP Advertisement";
1725 type_str="Router advertisement";
1727 } /* switch icmp_code */
1729 case ICMP_RTRSOLICIT:
1730 type_str="Router solicitation";
1733 type_str="Time-to-live exceeded";
1734 if (icmp_code < N_TIMXCEED) {
1735 g_snprintf(code_str, 64, "(%s)", ttl_str[icmp_code]);
1737 g_snprintf(code_str, 64, "(Unknown - error?)");
1740 case ICMP_PARAMPROB:
1741 type_str="Parameter problem";
1742 if (icmp_code < N_PARAMPROB) {
1743 g_snprintf(code_str, 64, "(%s)", par_str[icmp_code]);
1745 g_snprintf(code_str, 64, "(Unknown - error?)");
1749 type_str="Timestamp request";
1751 case ICMP_TSTAMPREPLY:
1752 type_str="Timestamp reply";
1755 type_str="Information request";
1757 case ICMP_IREQREPLY:
1758 type_str="Information reply";
1761 type_str="Address mask request";
1763 case ICMP_MASKREPLY:
1764 type_str="Address mask reply";
1767 type_str="Unknown ICMP (obsolete or malformed?)";
1771 if (check_col(pinfo->cinfo, COL_INFO)) {
1772 col_add_str(pinfo->cinfo, COL_INFO, type_str);
1773 if (code_str[0] != '\0')
1774 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", code_str);
1778 length = tvb_length(tvb);
1779 reported_length = tvb_reported_length(tvb);
1780 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1781 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1782 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1785 icmp_type, type_str);
1786 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1789 icmp_code, code_str);
1791 if (!pinfo->fragmented && length >= reported_length) {
1792 /* The packet isn't part of a fragmented datagram and isn't
1793 truncated, so we can checksum it. */
1795 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1797 if (computed_cksum == 0) {
1798 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1800 "Checksum: 0x%04x [correct]", cksum);
1802 item = proto_tree_add_boolean(icmp_tree, hf_icmp_checksum_bad,
1804 PROTO_ITEM_SET_HIDDEN(item);
1805 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1807 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1808 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1811 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1814 /* Decode the second 4 bytes of the packet. */
1815 switch (icmp_type) {
1816 case ICMP_ECHOREPLY:
1819 case ICMP_TSTAMPREPLY:
1821 case ICMP_IREQREPLY:
1823 case ICMP_MASKREPLY:
1824 proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, FALSE);
1825 proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2, FALSE);
1829 switch (icmp_code) {
1830 case ICMP_FRAG_NEEDED:
1831 proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6, 2, FALSE);
1836 case ICMP_RTRADVERT:
1837 num_addrs = tvb_get_guint8(tvb, 4);
1838 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1840 addr_entry_size = tvb_get_guint8(tvb, 5);
1841 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1843 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1844 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1847 case ICMP_PARAMPROB:
1848 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1849 tvb_get_guint8(tvb, 4));
1853 proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4, FALSE);
1857 /* Decode the additional information in the packet. */
1858 switch (icmp_type) {
1861 case ICMP_PARAMPROB:
1862 case ICMP_SOURCEQUENCH:
1864 /* Save the current value of the "we're inside an error packet"
1865 flag, and set that flag; subdissectors may treat packets
1866 that are the payload of error packets differently from
1868 save_in_error_pkt = pinfo->in_error_pkt;
1869 pinfo->in_error_pkt = TRUE;
1871 /* Decode the IP header and first 64 bits of data from the
1872 original datagram. */
1873 next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1875 /* There is a collision between RFC 1812 and draft-ietf-mpls-icmp-02.
1876 We don't know how to decode the 128th and following bytes of the ICMP payload.
1877 According to draft-ietf-mpls-icmp-02, these bytes should be decoded as MPLS extensions
1878 whereas RFC 1812 tells us to decode them as a portion of the original packet.
1879 Let the user decide.
1881 Here the user decided to favor MPLS extensions.
1882 Force the IP dissector to decode only the first 128 bytes. */
1883 if ((tvb_reported_length(tvb) > 8 + 128) &&
1884 favor_icmp_mpls_ext && (tvb_get_ntohs(tvb, 8 + 2) > 128))
1885 set_actual_length(next_tvb, 128);
1887 call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1889 /* Restore the "we're inside an error packet" flag. */
1890 pinfo->in_error_pkt = save_in_error_pkt;
1892 /* Decode MPLS extensions if the payload has at least 128 bytes, and
1893 - the original packet in the ICMP payload has less than 128 bytes, or
1894 - the user favors the MPLS extensions analysis */
1895 if ((tvb_reported_length(tvb) > 8 + 128)
1896 && (tvb_get_ntohs(tvb, 8 + 2) <= 128 || favor_icmp_mpls_ext))
1897 dissect_mpls_extensions(tvb, 8 + 128, icmp_tree);
1901 case ICMP_ECHOREPLY:
1903 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1907 case ICMP_RTRADVERT:
1908 if (addr_entry_size == 2) {
1909 for (i = 0; i < num_addrs; i++) {
1910 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1911 "Router address: %s",
1912 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1913 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1914 "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1916 if ((icmp_code == 0) || (icmp_code == 16)) {
1918 dissect_mip_extensions(tvb, 8 + i*8, icmp_tree);
1921 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1926 case ICMP_TSTAMPREPLY:
1927 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1928 tvb_get_ntohl(tvb, 8));
1929 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1930 tvb_get_ntohl(tvb, 12));
1931 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1932 tvb_get_ntohl(tvb, 16));
1936 case ICMP_MASKREPLY:
1937 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1938 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1945 proto_register_ip(void)
1947 static hf_register_info hf[] = {
1950 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1954 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1958 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1961 { &hf_ip_dsfield_dscp,
1962 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1963 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1966 { &hf_ip_dsfield_ect,
1967 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1971 { &hf_ip_dsfield_ce,
1972 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1977 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1980 { &hf_ip_tos_precedence,
1981 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1986 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1990 { &hf_ip_tos_throughput,
1991 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1995 { &hf_ip_tos_reliability,
1996 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
2001 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
2006 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
2010 { "Identification", "ip.id", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2014 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
2018 { "Destination Host", "ip.dst_host", FT_STRING, BASE_NONE, NULL, 0x0,
2022 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
2026 { "Source Host", "ip.src_host", FT_STRING, BASE_NONE, NULL, 0x0,
2030 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
2034 { "Source or Destination Host", "ip.host", FT_STRING, BASE_NONE, NULL, 0x0,
2038 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
2042 { "Reserved bit", "ip.flags.rb", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_RF >> 12,
2046 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF >> 12,
2050 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF >> 12,
2053 { &hf_ip_frag_offset,
2054 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
2058 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
2062 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
2066 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
2069 { &hf_ip_checksum_good,
2070 { "Good", "ip.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2071 "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
2073 { &hf_ip_checksum_bad,
2074 { "Bad ", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2075 "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
2077 { &hf_ip_fragment_overlap,
2078 { "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2079 "Fragment overlaps with other fragments", HFILL }},
2081 { &hf_ip_fragment_overlap_conflict,
2082 { "Conflicting data in fragment overlap", "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2083 "Overlapping fragments contained conflicting data", HFILL }},
2085 { &hf_ip_fragment_multiple_tails,
2086 { "Multiple tail fragments found", "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2087 "Several tails were found when defragmenting the packet", HFILL }},
2089 { &hf_ip_fragment_too_long_fragment,
2090 { "Fragment too long", "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2091 "Fragment contained data past end of packet", HFILL }},
2093 { &hf_ip_fragment_error,
2094 { "Defragmentation error", "ip.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2095 "Defragmentation error due to illegal fragments", HFILL }},
2098 { "IP Fragment", "ip.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2099 "IP Fragment", HFILL }},
2102 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2103 "IP Fragments", HFILL }},
2105 { &hf_ip_reassembled_in,
2106 { "Reassembled IP in frame", "ip.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2107 "This IP packet is reassembled in this frame", HFILL }}
2109 static gint *ett[] = {
2116 &ett_ip_option_route,
2117 &ett_ip_option_timestamp,
2122 module_t *ip_module;
2124 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
2125 proto_register_field_array(proto_ip, hf, array_length(hf));
2126 proto_register_subtree_array(ett, array_length(ett));
2128 /* subdissector code */
2129 ip_dissector_table = register_dissector_table("ip.proto",
2130 "IP protocol", FT_UINT8, BASE_DEC);
2132 /* Register configuration options */
2133 ip_module = prefs_register_protocol(proto_ip, NULL);
2134 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
2135 "Decode IPv4 TOS field as DiffServ field",
2136 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field (see RFC2474/RFC2475)",
2138 prefs_register_bool_preference(ip_module, "defragment",
2139 "Reassemble fragmented IP datagrams",
2140 "Whether fragmented IP datagrams should be reassembled",
2142 prefs_register_bool_preference(ip_module, "summary_in_tree",
2143 "Show IP summary in protocol tree",
2144 "Whether the IP summary line should be shown in the protocol tree",
2145 &ip_summary_in_tree);
2146 prefs_register_bool_preference(ip_module, "check_checksum" ,
2147 "Validate the IP checksum if possible",
2148 "Whether to validate the IP checksum",
2149 &ip_check_checksum);
2151 register_dissector("ip", dissect_ip, proto_ip);
2152 register_init_routine(ip_defragment_init);
2153 ip_tap=register_tap("ip");
2157 proto_reg_handoff_ip(void)
2159 dissector_handle_t ip_handle;
2161 data_handle = find_dissector("data");
2162 ip_handle = find_dissector("ip");
2163 dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
2164 dissector_add("ppp.protocol", PPP_IP, ip_handle);
2165 dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
2166 dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
2167 dissector_add("gre.proto", GRE_WCCP, ip_handle);
2168 dissector_add("llc.dsap", SAP_IP, ip_handle);
2169 dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
2170 dissector_add("null.type", BSD_AF_INET, ip_handle);
2171 dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
2172 dissector_add("osinl.excl", NLPID_IP, ip_handle);
2173 dissector_add("fr.ietf", NLPID_IP, ip_handle);
2174 dissector_add("x.25.spi", NLPID_IP, ip_handle);
2175 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1051, ip_handle);
2176 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1201, ip_handle);
2177 dissector_add_handle("udp.port", ip_handle);
2181 proto_register_icmp(void)
2183 static hf_register_info hf[] = {
2186 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
2190 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
2193 { &hf_icmp_checksum,
2194 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
2197 { &hf_icmp_checksum_bad,
2198 { "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2202 {"Identifier", "icmp.ident", FT_UINT16, BASE_HEX, NULL, 0x0,
2206 {"Sequence number", "icmp.seq", FT_UINT16, BASE_HEX, NULL, 0x0,
2210 {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL, 0x0,
2213 { &hf_icmp_redir_gw,
2214 {"Gateway address", "icmp.redir_gw", FT_IPv4, BASE_NONE, NULL, 0x0,
2217 { &hf_icmp_mip_type,
2218 { "Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
2219 VALS(mip_extensions), 0x0,"", HFILL}},
2221 { &hf_icmp_mip_length,
2222 { "Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL, 0x0,
2225 { &hf_icmp_mip_prefix_length,
2226 { "Prefix Length", "icmp.mip.prefixlength", FT_UINT8, BASE_DEC, NULL, 0x0,
2230 { "Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC, NULL, 0x0,
2233 { &hf_icmp_mip_life,
2234 { "Registration Lifetime", "icmp.mip.life", FT_UINT16, BASE_DEC, NULL, 0x0,
2237 { &hf_icmp_mip_flags,
2238 { "Flags", "icmp.mip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
2242 { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
2243 "Registration with this FA is required", HFILL }},
2246 { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
2247 "This FA will not accept requests at this time", HFILL }},
2250 { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
2251 "Home Agent Services Offered", HFILL }},
2254 { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
2255 "Foreign Agent Services Offered", HFILL }},
2258 { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
2259 "Minimal encapsulation tunneled datagram support", HFILL }},
2262 { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
2263 "GRE encapsulated tunneled datagram support", HFILL }},
2266 { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
2267 "Van Jacobson Header Compression Support", HFILL }},
2270 { "Reserved", "icmp.mip.res", FT_BOOLEAN, 8, NULL, 1,
2271 "Reserved", HFILL }},
2273 { &hf_icmp_mip_reserved,
2274 { "Reserved", "icmp.mip.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
2278 { "Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE, NULL, 0x0,
2281 { &hf_icmp_mip_challenge,
2282 { "Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE, NULL, 0x0,
2286 { "ICMP Extensions for MPLS", "icmp.mpls", FT_NONE, BASE_NONE, NULL, 0x0,
2289 { &hf_icmp_mpls_version,
2290 { "Version", "icmp.mpls.version", FT_UINT8, BASE_DEC, NULL, 0x0,
2293 { &hf_icmp_mpls_reserved,
2294 { "Reserved", "icmp.mpls.res", FT_UINT16, BASE_HEX, NULL, 0x0,
2297 { &hf_icmp_mpls_checksum,
2298 { "Checksum", "icmp.mpls.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
2301 { &hf_icmp_mpls_checksum_bad,
2302 { "Bad Checksum", "icmp.mpls.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2305 { &hf_icmp_mpls_length,
2306 { "Length", "icmp.mpls.length", FT_UINT16, BASE_HEX, NULL, 0x0,
2309 { &hf_icmp_mpls_class,
2310 { "Class", "icmp.mpls.class", FT_UINT8, BASE_DEC, NULL, 0x0,
2313 { &hf_icmp_mpls_c_type,
2314 { "C-Type", "icmp.mpls.ctype", FT_UINT8, BASE_DEC, NULL, 0x0,
2317 { &hf_icmp_mpls_label,
2318 { "Label", "icmp.mpls.label", FT_UINT24, BASE_DEC, NULL, 0x00fffff0,
2321 { &hf_icmp_mpls_exp,
2322 { "Experimental", "icmp.mpls.exp", FT_UINT24, BASE_DEC,
2327 { "Stack bit", "icmp.mpls.s", FT_BOOLEAN, 24, TFS(&flags_set_truth), 0x01,
2330 { &hf_icmp_mpls_ttl,
2331 { "Time to live", "icmp.mpls.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
2335 static gint *ett[] = {
2338 &ett_icmp_mip_flags,
2339 /* MPLS extensions */
2341 &ett_icmp_mpls_object,
2342 &ett_icmp_mpls_stack_object
2345 module_t *icmp_module;
2347 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
2349 proto_register_field_array(proto_icmp, hf, array_length(hf));
2350 proto_register_subtree_array(ett, array_length(ett));
2352 icmp_module = prefs_register_protocol(proto_icmp, NULL);
2354 prefs_register_bool_preference(icmp_module, "favor_icmp_mpls",
2355 "Favor ICMP extensions for MPLS",
2356 "Whether the 128th and following bytes of the ICMP payload should be decoded as MPLS extensions or as a portion of the original packet",
2357 &favor_icmp_mpls_ext);
2361 proto_reg_handoff_icmp(void)
2363 dissector_handle_t icmp_handle;
2366 * Get handle for the IP dissector.
2368 ip_handle = find_dissector("ip");
2370 icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
2371 dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);