2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.163 2002/02/27 05:45:48 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
33 #ifdef HAVE_NETINET_IN_H
34 # include <netinet/in.h>
41 #ifdef NEED_SNPRINTF_H
42 # include "snprintf.h"
45 #include <epan/packet.h>
46 #include <epan/resolv.h>
49 #include "reassemble.h"
55 #include "packet-ip.h"
56 #include "packet-ipsec.h"
60 static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
62 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
63 static gboolean g_ip_dscp_actif = TRUE;
65 /* Defragment fragmented IP datagrams */
66 static gboolean ip_defragment = FALSE;
68 /* Place IP summary in proto tree */
69 static gboolean ip_summary_in_tree = TRUE;
71 static int proto_ip = -1;
72 static int hf_ip_version = -1;
73 static int hf_ip_hdr_len = -1;
74 static int hf_ip_dsfield = -1;
75 static int hf_ip_dsfield_dscp = -1;
76 static int hf_ip_dsfield_ect = -1;
77 static int hf_ip_dsfield_ce = -1;
78 static int hf_ip_tos = -1;
79 static int hf_ip_tos_precedence = -1;
80 static int hf_ip_tos_delay = -1;
81 static int hf_ip_tos_throughput = -1;
82 static int hf_ip_tos_reliability = -1;
83 static int hf_ip_tos_cost = -1;
84 static int hf_ip_len = -1;
85 static int hf_ip_id = -1;
86 static int hf_ip_dst = -1;
87 static int hf_ip_src = -1;
88 static int hf_ip_addr = -1;
89 static int hf_ip_flags = -1;
90 static int hf_ip_flags_df = -1;
91 static int hf_ip_flags_mf = -1;
92 static int hf_ip_frag_offset = -1;
93 static int hf_ip_ttl = -1;
94 static int hf_ip_proto = -1;
95 static int hf_ip_checksum = -1;
96 static int hf_ip_checksum_bad = -1;
97 static int hf_ip_fragments = -1;
98 static int hf_ip_fragment = -1;
99 static int hf_ip_fragment_overlap = -1;
100 static int hf_ip_fragment_overlap_conflict = -1;
101 static int hf_ip_fragment_multiple_tails = -1;
102 static int hf_ip_fragment_too_long_fragment = -1;
103 static int hf_ip_fragment_error = -1;
105 static gint ett_ip = -1;
106 static gint ett_ip_dsfield = -1;
107 static gint ett_ip_tos = -1;
108 static gint ett_ip_off = -1;
109 static gint ett_ip_options = -1;
110 static gint ett_ip_option_sec = -1;
111 static gint ett_ip_option_route = -1;
112 static gint ett_ip_option_timestamp = -1;
113 static gint ett_ip_fragments = -1;
114 static gint ett_ip_fragment = -1;
116 /* Used by IPv6 as well, so not static */
117 dissector_table_t ip_dissector_table;
119 static dissector_handle_t ip_handle;
120 static dissector_handle_t data_handle;
122 static int proto_icmp = -1;
123 static int hf_icmp_type = -1;
124 static int hf_icmp_code = -1;
125 static int hf_icmp_checksum = -1;
126 static int hf_icmp_checksum_bad = -1;
129 static int hf_icmp_mip_type = -1;
130 static int hf_icmp_mip_length = -1;
131 static int hf_icmp_mip_prefix_length = -1;
132 static int hf_icmp_mip_seq = -1;
133 static int hf_icmp_mip_life = -1;
134 static int hf_icmp_mip_flags = -1;
135 static int hf_icmp_mip_r = -1;
136 static int hf_icmp_mip_b = -1;
137 static int hf_icmp_mip_h = -1;
138 static int hf_icmp_mip_f = -1;
139 static int hf_icmp_mip_m = -1;
140 static int hf_icmp_mip_g = -1;
141 static int hf_icmp_mip_v = -1;
142 static int hf_icmp_mip_res = -1;
143 static int hf_icmp_mip_reserved = -1;
144 static int hf_icmp_mip_coa = -1;
145 static int hf_icmp_mip_challenge = -1;
147 static gint ett_icmp = -1;
148 static gint ett_icmp_mip = -1;
149 static gint ett_icmp_mip_flags = -1;
151 /* ICMP definitions */
153 #define ICMP_ECHOREPLY 0
154 #define ICMP_UNREACH 3
155 #define ICMP_SOURCEQUENCH 4
156 #define ICMP_REDIRECT 5
158 #define ICMP_RTRADVERT 9
159 #define ICMP_RTRSOLICIT 10
160 #define ICMP_TIMXCEED 11
161 #define ICMP_PARAMPROB 12
162 #define ICMP_TSTAMP 13
163 #define ICMP_TSTAMPREPLY 14
165 #define ICMP_IREQREPLY 16
166 #define ICMP_MASKREQ 17
167 #define ICMP_MASKREPLY 18
169 /* ICMP UNREACHABLE */
171 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
172 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
173 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
174 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
175 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
176 #define ICMP_SR_FAILED 5 /* Source Route failed */
177 #define ICMP_NET_UNKNOWN 6
178 #define ICMP_HOST_UNKNOWN 7
179 #define ICMP_HOST_ISOLATED 8
180 #define ICMP_NET_ANO 9
181 #define ICMP_HOST_ANO 10
182 #define ICMP_NET_UNR_TOS 11
183 #define ICMP_HOST_UNR_TOS 12
184 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
185 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
186 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
189 /* IP structs and definitions */
193 guint8 ip_v_hl; /* combines ip_v and ip_hl */
205 /* Offsets of fields within an IP header. */
217 /* Minimum IP header length. */
218 #define IPH_MIN_LEN 20
221 #define IP_CE 0x8000 /* Flag: "Congestion" */
222 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
223 #define IP_MF 0x2000 /* Flag: "More Fragments" */
224 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
226 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
227 #define IPDSFIELD_DSCP_MASK 0xFC
228 #define IPDSFIELD_ECN_MASK 0x03
229 #define IPDSFIELD_DSCP_SHIFT 2
230 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
231 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
232 #define IPDSFIELD_DSCP_DEFAULT 0x00
233 #define IPDSFIELD_DSCP_CS1 0x08
234 #define IPDSFIELD_DSCP_CS2 0x10
235 #define IPDSFIELD_DSCP_CS3 0x18
236 #define IPDSFIELD_DSCP_CS4 0x20
237 #define IPDSFIELD_DSCP_CS5 0x28
238 #define IPDSFIELD_DSCP_CS6 0x30
239 #define IPDSFIELD_DSCP_CS7 0x38
240 #define IPDSFIELD_DSCP_AF11 0x0A
241 #define IPDSFIELD_DSCP_AF12 0x0C
242 #define IPDSFIELD_DSCP_AF13 0x0E
243 #define IPDSFIELD_DSCP_AF21 0x12
244 #define IPDSFIELD_DSCP_AF22 0x14
245 #define IPDSFIELD_DSCP_AF23 0x16
246 #define IPDSFIELD_DSCP_AF31 0x1A
247 #define IPDSFIELD_DSCP_AF32 0x1C
248 #define IPDSFIELD_DSCP_AF33 0x1E
249 #define IPDSFIELD_DSCP_AF41 0x22
250 #define IPDSFIELD_DSCP_AF42 0x24
251 #define IPDSFIELD_DSCP_AF43 0x26
252 #define IPDSFIELD_DSCP_EF 0x2E
253 #define IPDSFIELD_ECT_MASK 0x02
254 #define IPDSFIELD_CE_MASK 0x01
256 /* IP TOS, superseded by the DS Field, RFC 2474. */
257 #define IPTOS_TOS_MASK 0x1E
258 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
259 #define IPTOS_NONE 0x00
260 #define IPTOS_LOWCOST 0x02
261 #define IPTOS_RELIABILITY 0x04
262 #define IPTOS_THROUGHPUT 0x08
263 #define IPTOS_LOWDELAY 0x10
264 #define IPTOS_SECURITY 0x1E
266 #define IPTOS_PREC_MASK 0xE0
267 #define IPTOS_PREC_SHIFT 5
268 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
269 #define IPTOS_PREC_NETCONTROL 7
270 #define IPTOS_PREC_INTERNETCONTROL 6
271 #define IPTOS_PREC_CRITIC_ECP 5
272 #define IPTOS_PREC_FLASHOVERRIDE 4
273 #define IPTOS_PREC_FLASH 3
274 #define IPTOS_PREC_IMMEDIATE 2
275 #define IPTOS_PREC_PRIORITY 1
276 #define IPTOS_PREC_ROUTINE 0
279 #define IPOPT_COPY 0x80
281 #define IPOPT_CONTROL 0x00
282 #define IPOPT_RESERVED1 0x20
283 #define IPOPT_MEASUREMENT 0x40
284 #define IPOPT_RESERVED2 0x60
286 #define IPOPT_END (0 |IPOPT_CONTROL)
287 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
288 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
289 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
290 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
291 #define IPOPT_RR (7 |IPOPT_CONTROL)
292 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
293 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
294 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
296 /* IP option lengths */
297 #define IPOLEN_SEC 11
298 #define IPOLEN_LSRR_MIN 3
299 #define IPOLEN_TIMESTAMP_MIN 5
300 #define IPOLEN_RR_MIN 3
302 #define IPOLEN_SSRR_MIN 3
305 #define IPSEC_UNCLASSIFIED 0x0000
306 #define IPSEC_CONFIDENTIAL 0xF135
307 #define IPSEC_EFTO 0x789A
308 #define IPSEC_MMMM 0xBC4D
309 #define IPSEC_RESTRICTED 0xAF13
310 #define IPSEC_SECRET 0xD788
311 #define IPSEC_TOPSECRET 0x6BC5
312 #define IPSEC_RESERVED1 0x35E2
313 #define IPSEC_RESERVED2 0x9AF1
314 #define IPSEC_RESERVED3 0x4D78
315 #define IPSEC_RESERVED4 0x24BD
316 #define IPSEC_RESERVED5 0x135E
317 #define IPSEC_RESERVED6 0x89AF
318 #define IPSEC_RESERVED7 0xC4D6
319 #define IPSEC_RESERVED8 0xE26B
321 #define IPOPT_TS_TSONLY 0 /* timestamps only */
322 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
323 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
326 * defragmentation of IPv4
328 static GHashTable *ip_fragment_table = NULL;
331 ip_defragment_init(void)
333 fragment_table_init(&ip_fragment_table);
337 capture_ip(const u_char *pd, int offset, int len, packet_counts *ld) {
338 if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
342 switch (pd[offset + 9]) {
370 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
371 guint optlen, packet_info *pinfo, proto_tree *opt_tree)
373 proto_tree *field_tree = NULL;
376 static const value_string secl_vals[] = {
377 {IPSEC_UNCLASSIFIED, "Unclassified"},
378 {IPSEC_CONFIDENTIAL, "Confidential"},
379 {IPSEC_EFTO, "EFTO" },
380 {IPSEC_MMMM, "MMMM" },
381 {IPSEC_RESTRICTED, "Restricted" },
382 {IPSEC_SECRET, "Secret" },
383 {IPSEC_TOPSECRET, "Top secret" },
384 {IPSEC_RESERVED1, "Reserved" },
385 {IPSEC_RESERVED2, "Reserved" },
386 {IPSEC_RESERVED3, "Reserved" },
387 {IPSEC_RESERVED4, "Reserved" },
388 {IPSEC_RESERVED5, "Reserved" },
389 {IPSEC_RESERVED6, "Reserved" },
390 {IPSEC_RESERVED7, "Reserved" },
391 {IPSEC_RESERVED8, "Reserved" },
394 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
395 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
398 val = tvb_get_ntohs(tvb, offset);
399 proto_tree_add_text(field_tree, tvb, offset, 2,
400 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
403 val = tvb_get_ntohs(tvb, offset);
404 proto_tree_add_text(field_tree, tvb, offset, 2,
405 "Compartments: %u", val);
408 proto_tree_add_text(field_tree, tvb, offset, 2,
409 "Handling restrictions: %c%c",
410 tvb_get_guint8(tvb, offset),
411 tvb_get_guint8(tvb, offset + 1));
414 proto_tree_add_text(field_tree, tvb, offset, 3,
415 "Transmission control code: %c%c%c",
416 tvb_get_guint8(tvb, offset),
417 tvb_get_guint8(tvb, offset + 1),
418 tvb_get_guint8(tvb, offset + 2));
422 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
423 guint optlen, packet_info *pinfo, proto_tree *opt_tree)
425 proto_tree *field_tree = NULL;
431 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
433 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
435 optoffset += 2; /* skip past type and length */
436 optlen -= 2; /* subtract size of type and length */
438 ptr = tvb_get_guint8(tvb, offset + optoffset);
439 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
440 "Pointer: %d%s", ptr,
441 ((ptr < 4) ? " (points before first address)" :
442 ((ptr & 3) ? " (points to middle of address)" : "")));
445 ptr--; /* ptr is 1-origin */
449 proto_tree_add_text(field_tree, tvb, offset, optlen,
450 "(suboption would go past end of option)");
454 /* Avoids alignment problems on many architectures. */
455 tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
457 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
459 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
460 ((optoffset == ptr) ? " <- (current)" : ""));
467 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
468 guint optlen, packet_info *pinfo, proto_tree *opt_tree)
470 proto_tree_add_text(opt_tree, tvb, offset, optlen,
471 "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
476 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
477 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
479 proto_tree *field_tree = NULL;
484 static const value_string flag_vals[] = {
485 {IPOPT_TS_TSONLY, "Time stamps only" },
486 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
487 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
492 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
493 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
495 optoffset += 2; /* skip past type and length */
496 optlen -= 2; /* subtract size of type and length */
498 ptr = tvb_get_guint8(tvb, offset + optoffset);
499 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
500 "Pointer: %d%s", ptr,
501 ((ptr < 5) ? " (points before first address)" :
502 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
505 ptr--; /* ptr is 1-origin */
507 flg = tvb_get_guint8(tvb, offset + optoffset);
508 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
509 "Overflow: %u", flg >> 4);
511 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
512 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
517 if (flg == IPOPT_TS_TSANDADDR) {
519 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
520 "(suboption would go past end of option)");
523 tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
524 ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
526 proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
527 "Address = %s, time stamp = %u",
528 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
533 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
534 "(suboption would go past end of option)");
537 ts = tvb_get_ntohl(tvb, offset + optoffset);
539 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
540 "Time stamp = %u", ts);
547 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
548 guint optlen, packet_info *pinfo, proto_tree *opt_tree)
550 /* Router-Alert, as defined by RFC2113 */
551 int opt = tvb_get_ntohs(tvb, offset + 2);
552 static const value_string ra_opts[] = {
553 {0, "Every router examines packet"},
557 proto_tree_add_text(opt_tree, tvb, offset, optlen,
558 "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
562 static const ip_tcp_opt ipopts[] = {
585 dissect_ipopt_security
589 "Strict source route",
590 &ett_ip_option_route,
597 "Loose source route",
598 &ett_ip_option_route,
606 &ett_ip_option_route,
622 &ett_ip_option_timestamp,
624 IPOLEN_TIMESTAMP_MIN,
625 dissect_ipopt_timestamp
637 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
639 /* Dissect the IP or TCP options in a packet. */
641 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
642 const ip_tcp_opt *opttab, int nopts, int eol,
643 packet_info *pinfo, proto_tree *opt_tree)
646 const ip_tcp_opt *optp;
647 opt_len_type len_type;
650 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
651 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
652 int, guint, packet_info *, proto_tree *);
656 opt = tvb_get_guint8(tvb, offset);
657 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
658 if (optp->optcode == opt)
661 if (optp == &opttab[nopts]) {
662 /* We assume that the only NO_LENGTH options are EOL and NOP options,
663 so that we can treat unknown options as VARIABLE_LENGTH with a
664 minimum of 2, and at least be able to move on to the next option
665 by using the length in the option. */
666 optp = NULL; /* indicate that we don't know this option */
667 len_type = VARIABLE_LENGTH;
669 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
673 len_type = optp->len_type;
674 optlen = optp->optlen;
676 dissect = optp->dissect;
678 --length; /* account for type byte */
679 if (len_type != NO_LENGTH) {
680 /* Option has a length. Is it in the packet? */
682 /* Bogus - packet must at least include option code byte and
684 proto_tree_add_text(opt_tree, tvb, offset, 1,
685 "%s (length byte past end of options)", name);
688 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
689 --length; /* account for length byte */
691 /* Bogus - option length is too short to include option code and
693 proto_tree_add_text(opt_tree, tvb, offset, 2,
694 "%s (with too-short option length = %u byte%s)", name,
695 len, plurality(len, "", "s"));
697 } else if (len - 2 > length) {
698 /* Bogus - option goes past the end of the header. */
699 proto_tree_add_text(opt_tree, tvb, offset, length,
700 "%s (option length = %u byte%s says option goes past end of options)",
701 name, len, plurality(len, "", "s"));
703 } else if (len_type == FIXED_LENGTH && len != optlen) {
704 /* Bogus - option length isn't what it's supposed to be for this
706 proto_tree_add_text(opt_tree, tvb, offset, len,
707 "%s (with option length = %u byte%s; should be %u)", name,
708 len, plurality(len, "", "s"), optlen);
710 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
711 /* Bogus - option length is less than what it's supposed to be for
713 proto_tree_add_text(opt_tree, tvb, offset, len,
714 "%s (with option length = %u byte%s; should be >= %u)", name,
715 len, plurality(len, "", "s"), optlen);
719 proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
720 name, len, plurality(len, "", "s"));
722 if (dissect != NULL) {
723 /* Option has a dissector. */
724 (*dissect)(optp, tvb, offset, len, pinfo, opt_tree);
726 /* Option has no data, hence no dissector. */
727 proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
730 len -= 2; /* subtract size of type and length */
735 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
743 const value_string dscp_vals[] = {
744 { IPDSFIELD_DSCP_DEFAULT, "Default" },
745 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
746 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
747 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
748 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
749 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
750 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
751 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
752 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
753 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
754 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
755 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
756 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
757 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
758 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
759 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
760 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
761 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
762 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
763 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
764 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
767 static const value_string precedence_vals[] = {
768 { IPTOS_PREC_ROUTINE, "routine" },
769 { IPTOS_PREC_PRIORITY, "priority" },
770 { IPTOS_PREC_IMMEDIATE, "immediate" },
771 { IPTOS_PREC_FLASH, "flash" },
772 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
773 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
774 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
775 { IPTOS_PREC_NETCONTROL, "network control" },
778 static const value_string iptos_vals[] = {
779 { IPTOS_NONE, "None" },
780 { IPTOS_LOWCOST, "Minimize cost" },
781 { IPTOS_RELIABILITY, "Maximize reliability" },
782 { IPTOS_THROUGHPUT, "Maximize throughput" },
783 { IPTOS_LOWDELAY, "Minimize delay" },
784 { IPTOS_SECURITY, "Maximize security" },
788 static const true_false_string tos_set_low = {
793 static const true_false_string tos_set_high = {
798 static const true_false_string flags_set_truth = {
803 static guint16 ip_checksum(const guint8 *ptr, int len)
807 cksum_vec[0].ptr = ptr;
808 cksum_vec[0].len = len;
809 return in_cksum(&cksum_vec[0], 1);
813 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
816 proto_tree *ip_tree = NULL, *field_tree;
819 guint hlen, optlen, len;
823 fragment_data *ipfd_head;
825 gboolean update_col_info = TRUE;
826 gboolean save_fragmented;
828 if (check_col(pinfo->cinfo, COL_PROTOCOL))
829 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
830 if (check_col(pinfo->cinfo, COL_INFO))
831 col_clear(pinfo->cinfo, COL_INFO);
833 /* Avoids alignment problems on many architectures. */
834 tvb_memcpy(tvb, (guint8 *)&iph, offset, sizeof(e_ip));
835 iph.ip_len = ntohs(iph.ip_len);
836 iph.ip_id = ntohs(iph.ip_id);
837 iph.ip_off = ntohs(iph.ip_off);
838 iph.ip_sum = ntohs(iph.ip_sum);
840 /* Length of IP datagram.
841 XXX - what if this is greater than the reported length of the
842 tvbuff? This could happen, for example, in an IP datagram
843 inside an ICMP datagram; we need to somehow let the
844 dissector we call know that, as it might want to avoid
845 doing its checksumming. */
848 /* Adjust the length of this tvbuff to include only the IP datagram. */
849 set_actual_length(tvb, len);
851 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
854 if (ip_summary_in_tree && hlen >= IPH_MIN_LEN) {
855 ti = proto_tree_add_protocol_format(tree, proto_ip, tvb, offset, hlen,
856 "Internet Protocol, Src Addr: %s (%s), Dst Addr: %s (%s)",
857 get_hostname(iph.ip_src), ip_to_str((guint8 *) &iph.ip_src),
858 get_hostname(iph.ip_dst), ip_to_str((guint8 *) &iph.ip_dst));
860 ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
862 ip_tree = proto_item_add_subtree(ti, ett_ip);
865 if (hlen < IPH_MIN_LEN) {
866 if (check_col(pinfo->cinfo, COL_INFO))
867 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
870 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
871 "Header length: %u bytes (bogus, must be at least %u)", hlen,
878 * Compute the checksum of the IP header.
880 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
883 proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1, hi_nibble(iph.ip_v_hl));
884 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
885 "Header length: %u bytes", hlen);
887 if (g_ip_dscp_actif) {
888 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph.ip_tos,
889 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph.ip_tos,
890 IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
891 "Unknown DSCP"),IPDSFIELD_ECN(iph.ip_tos));
893 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
894 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph.ip_tos);
895 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph.ip_tos);
896 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph.ip_tos);
898 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph.ip_tos,
899 "Type of service: 0x%02x (%s)", iph.ip_tos,
900 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
902 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
903 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph.ip_tos);
904 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph.ip_tos);
905 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph.ip_tos);
906 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph.ip_tos);
907 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph.ip_tos);
909 proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph.ip_len);
910 proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph.ip_id);
912 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
913 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
914 field_tree = proto_item_add_subtree(tf, ett_ip_off);
915 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
916 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
918 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
919 (iph.ip_off & IP_OFFSET)*8);
921 proto_tree_add_uint(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, iph.ip_ttl);
922 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph.ip_p,
923 "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
926 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
927 "Header checksum: 0x%04x (correct)", iph.ip_sum);
930 proto_tree_add_boolean_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
931 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
932 "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph.ip_sum,
933 in_cksum_shouldbe(iph.ip_sum, ipsum));
936 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, iph.ip_src);
937 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, iph.ip_dst);
938 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, iph.ip_src);
939 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, iph.ip_dst);
941 /* Decode IP options, if any. */
942 if (hlen > sizeof (e_ip)) {
943 /* There's more than just the fixed-length header. Decode the
945 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
946 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
947 "Options: (%u bytes)", optlen);
948 field_tree = proto_item_add_subtree(tf, ett_ip_options);
949 dissect_ip_tcp_options(tvb, offset + 20, optlen,
950 ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
954 pinfo->ipproto = iph.ip_p;
956 pinfo->iplen = iph.ip_len;
958 pinfo->iphdrlen = lo_nibble(iph.ip_v_hl);
960 SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
961 SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
962 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
963 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
965 /* Skip over header + options */
967 nxt = iph.ip_p; /* XXX - what if this isn't the same for all fragments? */
969 /* If ip_defragment is on, this is a fragment, we have all the data
970 * in the fragment, and the header checksum is valid, then just add
971 * the fragment to the hashtable.
973 save_fragmented = pinfo->fragmented;
974 if (ip_defragment && (iph.ip_off & (IP_MF|IP_OFFSET)) &&
975 tvb_reported_length(tvb) <= tvb_length(tvb) && ipsum == 0) {
976 ipfd_head = fragment_add(tvb, offset, pinfo, iph.ip_id,
978 (iph.ip_off & IP_OFFSET)*8,
979 pinfo->iplen - (pinfo->iphdrlen*4),
982 if (ipfd_head != NULL) {
987 /* OK, we have the complete reassembled payload. */
988 /* show all fragments */
989 fi = proto_tree_add_item(ip_tree, hf_ip_fragments,
991 ft = proto_item_add_subtree(fi, ett_ip_fragments);
992 for (ipfd=ipfd_head->next; ipfd; ipfd=ipfd->next){
993 if (ipfd->flags & (FD_OVERLAP|FD_OVERLAPCONFLICT
994 |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
995 /* this fragment has some flags set, create a subtree
996 * for it and display the flags.
998 proto_tree *fet=NULL;
999 proto_item *fei=NULL;
1002 if (ipfd->flags & (FD_OVERLAPCONFLICT
1003 |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
1004 hf = hf_ip_fragment_error;
1006 hf = hf_ip_fragment;
1008 fei = proto_tree_add_none_format(ft, hf,
1010 "Frame:%u payload:%u-%u",
1013 ipfd->offset+ipfd->len-1
1015 fet = proto_item_add_subtree(fei, ett_ip_fragment);
1016 if (ipfd->flags&FD_OVERLAP) {
1017 proto_tree_add_boolean(fet,
1018 hf_ip_fragment_overlap, tvb, 0, 0,
1021 if (ipfd->flags&FD_OVERLAPCONFLICT) {
1022 proto_tree_add_boolean(fet,
1023 hf_ip_fragment_overlap_conflict, tvb, 0, 0,
1026 if (ipfd->flags&FD_MULTIPLETAILS) {
1027 proto_tree_add_boolean(fet,
1028 hf_ip_fragment_multiple_tails, tvb, 0, 0,
1031 if (ipfd->flags&FD_TOOLONGFRAGMENT) {
1032 proto_tree_add_boolean(fet,
1033 hf_ip_fragment_too_long_fragment, tvb, 0, 0,
1037 /* nothing of interest for this fragment */
1038 proto_tree_add_none_format(ft, hf_ip_fragment,
1040 "Frame:%u payload:%u-%u",
1043 ipfd->offset+ipfd->len-1
1047 if (ipfd_head->flags & (FD_OVERLAPCONFLICT
1048 |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
1049 if (check_col(pinfo->cinfo, COL_INFO)) {
1050 col_set_str(pinfo->cinfo, COL_INFO, "[Illegal fragments]");
1051 update_col_info = FALSE;
1055 /* Allocate a new tvbuff, referring to the reassembled payload. */
1056 next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen,
1057 ipfd_head->datalen);
1059 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
1060 were handed refers, so it'll get cleaned up when that tvbuff
1062 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1064 /* Add the defragmented data to the data source list. */
1065 add_new_data_source(pinfo->fd, next_tvb, "Reassembled IPv4");
1067 /* It's not fragmented. */
1068 pinfo->fragmented = FALSE;
1070 /* We don't have the complete reassembled payload. */
1074 /* If this is the first fragment, dissect its contents, otherwise
1075 just show it as a fragment.
1077 XXX - if we eventually don't save the reassembled contents of all
1078 fragmented datagrams, we may want to always reassemble. */
1079 if (iph.ip_off & IP_OFFSET) {
1080 /* Not the first fragment - don't dissect it. */
1083 /* First fragment, or not fragmented. Dissect what we have here. */
1085 /* Get a tvbuff for the payload. */
1086 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1089 * If this is the first fragment, but not the only fragment,
1090 * tell the next protocol that.
1092 if (iph.ip_off & IP_MF)
1093 pinfo->fragmented = TRUE;
1095 pinfo->fragmented = FALSE;
1099 if (next_tvb == NULL) {
1100 /* Just show this as a fragment. */
1101 if (check_col(pinfo->cinfo, COL_INFO))
1102 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1103 ipprotostr(iph.ip_p), iph.ip_p, (iph.ip_off & IP_OFFSET) * 8);
1104 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, tree);
1105 pinfo->fragmented = save_fragmented;
1109 /* Hand off to the next protocol.
1111 XXX - setting the columns only after trying various dissectors means
1112 that if one of those dissectors throws an exception, the frame won't
1113 even be labelled as an IP frame; ideally, if a frame being dissected
1114 throws an exception, it'll be labelled as a mangled frame of the
1115 type in question. */
1116 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
1117 /* Unknown protocol */
1118 if (update_col_info) {
1119 if (check_col(pinfo->cinfo, COL_INFO))
1120 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
1122 call_dissector(data_handle,next_tvb, pinfo, tree);
1124 pinfo->fragmented = save_fragmented;
1127 #define ICMP_MIP_EXTENSION_PAD 0
1128 #define ICMP_MIP_MOB_AGENT_ADV 16
1129 #define ICMP_MIP_PREFIX_LENGTHS 19
1130 #define ICMP_MIP_CHALLENGE 24
1132 static value_string mip_extensions[] = {
1133 { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
1134 { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1136 { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
1137 { ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
1142 * Dissect the mobile ip advertisement extensions.
1145 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, packet_info *pinfo,
1152 proto_tree *mip_tree=NULL;
1153 proto_tree *flags_tree=NULL;
1157 /* Not much to do if we're not parsing everything */
1160 while ((tvb_length(tvb) - offset) > 0) {
1162 type = tvb_get_guint8(tvb, offset + 0);
1164 length = tvb_get_guint8(tvb, offset + 1);
1168 ti = proto_tree_add_text(tree, tvb, offset,
1169 type?(length + 2):1,
1171 val_to_str(type, mip_extensions,
1173 mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1177 case ICMP_MIP_EXTENSION_PAD:
1178 /* One byte padding extension */
1179 /* Add our fields */
1181 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1185 case ICMP_MIP_MOB_AGENT_ADV:
1186 /* Mobility Agent Advertisement Extension (RFC 2002)*/
1187 /* Add our fields */
1189 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1193 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1196 /* sequence number */
1197 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset,
1200 /* Registration Lifetime */
1201 proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset,
1205 flags = tvb_get_guint8(tvb, offset);
1206 ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1208 flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1209 proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1210 proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1211 proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1212 proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1213 proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1214 proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1215 proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1216 proto_tree_add_boolean(flags_tree, hf_icmp_mip_res, tvb, offset, 1, flags);
1220 proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset,
1225 numCOAs = (length - 6) / 4;
1226 for (i=0; i<numCOAs; i++) {
1227 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset,
1232 case ICMP_MIP_PREFIX_LENGTHS:
1233 /* Prefix-Lengths Extension (RFC 2002)*/
1234 /* Add our fields */
1236 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1240 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1244 /* prefix lengths */
1245 for(i=0; i<length; i++) {
1246 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1251 case ICMP_MIP_CHALLENGE:
1252 /* Challenge Extension (RFC 3012)*/
1254 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1258 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1262 proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset,
1268 g_warning("Unknown type(%u)! I hope the length is right (%u)",
1275 } /* dissect_mip_extensions */
1277 static const gchar *unreach_str[] = {"Network unreachable",
1279 "Protocol unreachable",
1281 "Fragmentation needed",
1282 "Source route failed",
1283 "Destination network unknown",
1284 "Destination host unknown",
1285 "Source host isolated",
1286 "Network administratively prohibited",
1287 "Host administratively prohibited",
1288 "Network unreachable for TOS",
1289 "Host unreachable for TOS",
1290 "Communication administratively filtered",
1291 "Host precedence violation",
1292 "Precedence cutoff in effect"};
1294 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1296 static const gchar *redir_str[] = {"Redirect for network",
1297 "Redirect for host",
1298 "Redirect for TOS and network",
1299 "Redirect for TOS and host"};
1301 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1303 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
1304 "TTL equals 0 during reassembly"};
1306 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1308 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1310 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1313 * RFC 792 for basic ICMP.
1314 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1315 * RFC 1256 for router discovery messages.
1316 * RFC 2002 and 3012 for Mobile IP stuff.
1319 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1321 proto_tree *icmp_tree;
1325 guint length, reported_length;
1326 guint16 cksum, computed_cksum;
1327 gchar type_str[64], code_str[64] = "";
1328 guint8 num_addrs = 0;
1329 guint8 addr_entry_size = 0;
1331 volatile address save_dl_src;
1332 volatile address save_dl_dst;
1333 volatile address save_net_src;
1334 volatile address save_net_dst;
1335 volatile address save_src;
1336 volatile address save_dst;
1337 gboolean save_in_error_pkt;
1340 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1341 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1342 if (check_col(pinfo->cinfo, COL_INFO))
1343 col_clear(pinfo->cinfo, COL_INFO);
1345 /* To do: check for runts, errs, etc. */
1346 icmp_type = tvb_get_guint8(tvb, 0);
1347 icmp_code = tvb_get_guint8(tvb, 1);
1348 cksum = tvb_get_ntohs(tvb, 2);
1350 switch (icmp_type) {
1351 case ICMP_ECHOREPLY:
1352 strcpy(type_str, "Echo (ping) reply");
1355 strcpy(type_str, "Destination unreachable");
1356 if (icmp_code < N_UNREACH) {
1357 sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1359 strcpy(code_str, "(Unknown - error?)");
1362 case ICMP_SOURCEQUENCH:
1363 strcpy(type_str, "Source quench (flow control)");
1366 strcpy(type_str, "Redirect");
1367 if (icmp_code < N_REDIRECT) {
1368 sprintf(code_str, "(%s)", redir_str[icmp_code]);
1370 strcpy(code_str, "(Unknown - error?)");
1374 strcpy(type_str, "Echo (ping) request");
1376 case ICMP_RTRADVERT:
1377 switch (icmp_code) {
1378 case 16: /* Mobile-Ip */
1379 strcpy(type_str, "Mobile IP Advertisement");
1382 strcpy(type_str, "Router advertisement");
1384 } /* switch icmp_code */
1386 case ICMP_RTRSOLICIT:
1387 strcpy(type_str, "Router solicitation");
1390 strcpy(type_str, "Time-to-live exceeded");
1391 if (icmp_code < N_TIMXCEED) {
1392 sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1394 strcpy(code_str, "(Unknown - error?)");
1397 case ICMP_PARAMPROB:
1398 strcpy(type_str, "Parameter problem");
1399 if (icmp_code < N_PARAMPROB) {
1400 sprintf(code_str, "(%s)", par_str[icmp_code]);
1402 strcpy(code_str, "(Unknown - error?)");
1406 strcpy(type_str, "Timestamp request");
1408 case ICMP_TSTAMPREPLY:
1409 strcpy(type_str, "Timestamp reply");
1412 strcpy(type_str, "Information request");
1414 case ICMP_IREQREPLY:
1415 strcpy(type_str, "Information reply");
1418 strcpy(type_str, "Address mask request");
1420 case ICMP_MASKREPLY:
1421 strcpy(type_str, "Address mask reply");
1424 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1428 if (check_col(pinfo->cinfo, COL_INFO))
1429 col_add_str(pinfo->cinfo, COL_INFO, type_str);
1432 length = tvb_length(tvb);
1433 reported_length = tvb_reported_length(tvb);
1434 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1435 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1436 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1439 icmp_type, type_str);
1440 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1443 icmp_code, code_str);
1445 if (!pinfo->fragmented && length >= reported_length) {
1446 /* The packet isn't part of a fragmented datagram and isn't
1447 truncated, so we can checksum it. */
1449 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1451 if (computed_cksum == 0) {
1452 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1454 "Checksum: 0x%04x (correct)", cksum);
1456 proto_tree_add_boolean_hidden(icmp_tree, hf_icmp_checksum_bad,
1458 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1460 "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1461 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1464 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1467 /* Decode the second 4 bytes of the packet. */
1468 switch (icmp_type) {
1469 case ICMP_ECHOREPLY:
1472 case ICMP_TSTAMPREPLY:
1474 case ICMP_IREQREPLY:
1476 case ICMP_MASKREPLY:
1477 proto_tree_add_text(icmp_tree, tvb, 4, 2, "Identifier: 0x%04x",
1478 tvb_get_ntohs(tvb, 4));
1479 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Sequence number: %02x:%02x",
1480 tvb_get_guint8(tvb, 6), tvb_get_guint8(tvb, 7));
1484 switch (icmp_code) {
1485 case ICMP_FRAG_NEEDED:
1486 proto_tree_add_text(icmp_tree, tvb, 6, 2, "MTU of next hop: %u",
1487 tvb_get_ntohs(tvb, 6));
1492 case ICMP_RTRADVERT:
1493 num_addrs = tvb_get_guint8(tvb, 4);
1494 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1496 addr_entry_size = tvb_get_guint8(tvb, 5);
1497 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1499 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1500 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1503 case ICMP_PARAMPROB:
1504 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1505 tvb_get_guint8(tvb, 4));
1509 proto_tree_add_text(icmp_tree, tvb, 4, 4, "Gateway address: %s",
1510 ip_to_str(tvb_get_ptr(tvb, 4, 4)));
1514 /* Decode the additional information in the packet. */
1515 switch (icmp_type) {
1518 case ICMP_PARAMPROB:
1519 case ICMP_SOURCEQUENCH:
1521 /* Decode the IP header and first 64 bits of data from the
1524 Set the columns non-writable, so that the packet list
1525 shows this as an ICMP packet, not as the type of packet
1526 for which the ICMP packet was generated. */
1527 col_set_writable(pinfo->cinfo, FALSE);
1529 /* Also, save the current values of the addresses, and restore
1530 them when we're finished dissecting the contained packet, so
1531 that the address columns in the summary don't reflect the
1532 contained packet, but reflect this packet instead. */
1533 save_dl_src = pinfo->dl_src;
1534 save_dl_dst = pinfo->dl_dst;
1535 save_net_src = pinfo->net_src;
1536 save_net_dst = pinfo->net_dst;
1537 save_src = pinfo->src;
1538 save_dst = pinfo->dst;
1540 /* Save the current value of the "we're inside an error packet"
1541 flag, and set that flag; subdissectors may treat packets
1542 that are the payload of error packets differently from
1544 save_in_error_pkt = pinfo->in_error_pkt;
1545 pinfo->in_error_pkt = TRUE;
1547 /* Dissect the contained packet.
1548 Catch ReportedBoundsError, and do nothing if we see it,
1549 because it's not an error if the contained packet is short;
1550 there's no guarantee that all of it was included.
1552 XXX - should catch BoundsError, and re-throw it after cleaning
1554 next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1556 call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1558 CATCH(ReportedBoundsError) {
1563 /* Restore the "we're inside an error packet" flag. */
1564 pinfo->in_error_pkt = save_in_error_pkt;
1566 /* Restore the addresses. */
1567 pinfo->dl_src = save_dl_src;
1568 pinfo->dl_dst = save_dl_dst;
1569 pinfo->net_src = save_net_src;
1570 pinfo->net_dst = save_net_dst;
1571 pinfo->src = save_src;
1572 pinfo->dst = save_dst;
1575 case ICMP_ECHOREPLY:
1577 call_dissector(data_handle,tvb_new_subset(tvb, 8,-1,tvb_reported_length_remaining(tvb,8)), pinfo, icmp_tree);
1580 case ICMP_RTRADVERT:
1581 if (addr_entry_size == 2) {
1582 for (i = 0; i < num_addrs; i++) {
1583 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1584 "Router address: %s",
1585 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1586 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1587 "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1589 if (icmp_code == 16) {
1591 dissect_mip_extensions(tvb,8 + i*8, pinfo, icmp_tree);
1594 call_dissector(data_handle,tvb_new_subset(tvb, 8,-1,tvb_reported_length_remaining(tvb,8)), pinfo, icmp_tree);
1598 case ICMP_TSTAMPREPLY:
1599 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1600 tvb_get_ntohl(tvb, 8));
1601 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1602 tvb_get_ntohl(tvb, 12));
1603 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1604 tvb_get_ntohl(tvb, 16));
1608 case ICMP_MASKREPLY:
1609 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1610 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1617 proto_register_ip(void)
1619 static hf_register_info hf[] = {
1622 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1626 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1630 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1633 { &hf_ip_dsfield_dscp,
1634 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1635 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1638 { &hf_ip_dsfield_ect,
1639 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1643 { &hf_ip_dsfield_ce,
1644 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1649 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1652 { &hf_ip_tos_precedence,
1653 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1658 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1662 { &hf_ip_tos_throughput,
1663 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1667 { &hf_ip_tos_reliability,
1668 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1673 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1678 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1682 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1686 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1690 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1694 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1698 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1702 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1706 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1709 { &hf_ip_frag_offset,
1710 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1714 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1718 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1722 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1725 { &hf_ip_checksum_bad,
1726 { "Bad Header checksum", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1729 { &hf_ip_fragment_overlap,
1730 { "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1731 "Fragment overlaps with other fragments", HFILL }},
1733 { &hf_ip_fragment_overlap_conflict,
1734 { "Conflicting data in fragment overlap", "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1735 "Overlapping fragments contained conflicting data", HFILL }},
1737 { &hf_ip_fragment_multiple_tails,
1738 { "Multiple tail fragments found", "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1739 "Several tails were found when defragmenting the packet", HFILL }},
1741 { &hf_ip_fragment_too_long_fragment,
1742 { "Fragment too long", "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1743 "Fragment contained data past end of packet", HFILL }},
1745 { &hf_ip_fragment_error,
1746 { "Defragmentation error", "ip.fragment.error", FT_NONE, BASE_NONE, NULL, 0x0,
1747 "Defragmentation error due to illegal fragments", HFILL }},
1750 { "IP Fragment", "ip.fragment", FT_NONE, BASE_NONE, NULL, 0x0,
1751 "IP Fragment", HFILL }},
1754 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1755 "IP Fragments", HFILL }},
1757 static gint *ett[] = {
1764 &ett_ip_option_route,
1765 &ett_ip_option_timestamp,
1769 module_t *ip_module;
1771 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1772 proto_register_field_array(proto_ip, hf, array_length(hf));
1773 proto_register_subtree_array(ett, array_length(ett));
1775 /* subdissector code */
1776 ip_dissector_table = register_dissector_table("ip.proto",
1777 "IP protocol", FT_UINT8, BASE_DEC);
1779 /* Register configuration options */
1780 ip_module = prefs_register_protocol(proto_ip, NULL);
1781 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1782 "Decode IPv4 TOS field as DiffServ field",
1783 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1785 prefs_register_bool_preference(ip_module, "defragment",
1786 "Reassemble fragmented IP datagrams",
1787 "Whether fragmented IP datagrams should be reassembled",
1789 prefs_register_bool_preference(ip_module, "ip_summary_in_tree",
1790 "Show IP summary in protocol tree",
1791 "Whether the IP summary line should be shown in the protocol tree",
1792 &ip_summary_in_tree);
1794 register_dissector("ip", dissect_ip, proto_ip);
1795 register_init_routine(ip_defragment_init);
1799 proto_reg_handoff_ip(void)
1801 dissector_handle_t ip_handle;
1803 data_handle = find_dissector("data");
1804 ip_handle = find_dissector("ip");
1805 dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
1806 dissector_add("ppp.protocol", PPP_IP, ip_handle);
1807 dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
1808 dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
1809 dissector_add("gre.proto", GRE_WCCP, ip_handle);
1810 dissector_add("llc.dsap", SAP_IP, ip_handle);
1811 dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
1812 dissector_add("null.type", BSD_AF_INET, ip_handle);
1813 dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
1814 dissector_add("fr.ietf", NLPID_IP, ip_handle);
1815 dissector_add("x.25.spi", NLPID_IP, ip_handle);
1819 proto_register_icmp(void)
1821 static hf_register_info hf[] = {
1824 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1828 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1831 { &hf_icmp_checksum,
1832 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1835 { &hf_icmp_checksum_bad,
1836 { "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1839 { &hf_icmp_mip_type,
1840 { "Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
1841 VALS(mip_extensions), 0x0,"", HFILL}},
1843 { &hf_icmp_mip_length,
1844 { "Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL, 0x0,
1847 { &hf_icmp_mip_prefix_length,
1848 { "Prefix Length", "icmp.mip.prefixlength", FT_UINT8, BASE_DEC, NULL, 0x0,
1852 { "Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC, NULL, 0x0,
1855 { &hf_icmp_mip_life,
1856 { "Registration Lifetime", "icmp.mip.life", FT_UINT16, BASE_DEC, NULL, 0x0,
1859 { &hf_icmp_mip_flags,
1860 { "Flags", "icmp.mip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1864 { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
1865 "Registration with this FA is required", HFILL }},
1868 { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
1869 "This FA will not accept requests at this time", HFILL }},
1872 { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
1873 "Home Agent Services Offered", HFILL }},
1876 { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
1877 "Foreign Agent Services Offered", HFILL }},
1880 { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
1881 "Minimal encapsulation tunneled datagram support", HFILL }},
1884 { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
1885 "GRE encapsulated tunneled datagram support", HFILL }},
1888 { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
1889 "Van Jacobson Header Compression Support", HFILL }},
1892 { "Reserved", "icmp.mip.res", FT_BOOLEAN, 8, NULL, 1,
1893 "Reserved", HFILL }},
1895 { &hf_icmp_mip_reserved,
1896 { "Reserved", "icmp.mip.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
1900 { "Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE, NULL, 0x0,
1903 { &hf_icmp_mip_challenge,
1904 { "Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE, NULL, 0x0,
1907 static gint *ett[] = {
1913 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
1915 proto_register_field_array(proto_icmp, hf, array_length(hf));
1916 proto_register_subtree_array(ett, array_length(ett));
1920 proto_reg_handoff_icmp(void)
1922 dissector_handle_t icmp_handle;
1925 * Get handle for the IP dissector.
1927 ip_handle = find_dissector("ip");
1929 icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
1930 dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);