2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.171 2002/07/15 20:54:45 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 fragment_items ip_frag_items = {
121 &hf_ip_fragment_overlap,
122 &hf_ip_fragment_overlap_conflict,
123 &hf_ip_fragment_multiple_tails,
124 &hf_ip_fragment_too_long_fragment,
125 &hf_ip_fragment_error,
129 /* Used by IPv6 as well, so not static */
130 dissector_table_t ip_dissector_table;
132 static dissector_handle_t ip_handle;
133 static dissector_handle_t data_handle;
135 static int proto_icmp = -1;
136 static int hf_icmp_type = -1;
137 static int hf_icmp_code = -1;
138 static int hf_icmp_checksum = -1;
139 static int hf_icmp_checksum_bad = -1;
142 static int hf_icmp_mip_type = -1;
143 static int hf_icmp_mip_length = -1;
144 static int hf_icmp_mip_prefix_length = -1;
145 static int hf_icmp_mip_seq = -1;
146 static int hf_icmp_mip_life = -1;
147 static int hf_icmp_mip_flags = -1;
148 static int hf_icmp_mip_r = -1;
149 static int hf_icmp_mip_b = -1;
150 static int hf_icmp_mip_h = -1;
151 static int hf_icmp_mip_f = -1;
152 static int hf_icmp_mip_m = -1;
153 static int hf_icmp_mip_g = -1;
154 static int hf_icmp_mip_v = -1;
155 static int hf_icmp_mip_res = -1;
156 static int hf_icmp_mip_reserved = -1;
157 static int hf_icmp_mip_coa = -1;
158 static int hf_icmp_mip_challenge = -1;
160 static gint ett_icmp = -1;
161 static gint ett_icmp_mip = -1;
162 static gint ett_icmp_mip_flags = -1;
164 /* ICMP definitions */
166 #define ICMP_ECHOREPLY 0
167 #define ICMP_UNREACH 3
168 #define ICMP_SOURCEQUENCH 4
169 #define ICMP_REDIRECT 5
171 #define ICMP_RTRADVERT 9
172 #define ICMP_RTRSOLICIT 10
173 #define ICMP_TIMXCEED 11
174 #define ICMP_PARAMPROB 12
175 #define ICMP_TSTAMP 13
176 #define ICMP_TSTAMPREPLY 14
178 #define ICMP_IREQREPLY 16
179 #define ICMP_MASKREQ 17
180 #define ICMP_MASKREPLY 18
182 /* ICMP UNREACHABLE */
184 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
185 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
186 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
187 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
188 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
189 #define ICMP_SR_FAILED 5 /* Source Route failed */
190 #define ICMP_NET_UNKNOWN 6
191 #define ICMP_HOST_UNKNOWN 7
192 #define ICMP_HOST_ISOLATED 8
193 #define ICMP_NET_ANO 9
194 #define ICMP_HOST_ANO 10
195 #define ICMP_NET_UNR_TOS 11
196 #define ICMP_HOST_UNR_TOS 12
197 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
198 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
199 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
202 /* IP structs and definitions */
206 guint8 ip_v_hl; /* combines ip_v and ip_hl */
218 /* Offsets of fields within an IP header. */
230 /* Minimum IP header length. */
231 #define IPH_MIN_LEN 20
234 #define IP_CE 0x8000 /* Flag: "Congestion" */
235 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
236 #define IP_MF 0x2000 /* Flag: "More Fragments" */
237 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
239 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
240 #define IPDSFIELD_DSCP_MASK 0xFC
241 #define IPDSFIELD_ECN_MASK 0x03
242 #define IPDSFIELD_DSCP_SHIFT 2
243 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
244 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
245 #define IPDSFIELD_DSCP_DEFAULT 0x00
246 #define IPDSFIELD_DSCP_CS1 0x08
247 #define IPDSFIELD_DSCP_CS2 0x10
248 #define IPDSFIELD_DSCP_CS3 0x18
249 #define IPDSFIELD_DSCP_CS4 0x20
250 #define IPDSFIELD_DSCP_CS5 0x28
251 #define IPDSFIELD_DSCP_CS6 0x30
252 #define IPDSFIELD_DSCP_CS7 0x38
253 #define IPDSFIELD_DSCP_AF11 0x0A
254 #define IPDSFIELD_DSCP_AF12 0x0C
255 #define IPDSFIELD_DSCP_AF13 0x0E
256 #define IPDSFIELD_DSCP_AF21 0x12
257 #define IPDSFIELD_DSCP_AF22 0x14
258 #define IPDSFIELD_DSCP_AF23 0x16
259 #define IPDSFIELD_DSCP_AF31 0x1A
260 #define IPDSFIELD_DSCP_AF32 0x1C
261 #define IPDSFIELD_DSCP_AF33 0x1E
262 #define IPDSFIELD_DSCP_AF41 0x22
263 #define IPDSFIELD_DSCP_AF42 0x24
264 #define IPDSFIELD_DSCP_AF43 0x26
265 #define IPDSFIELD_DSCP_EF 0x2E
266 #define IPDSFIELD_ECT_MASK 0x02
267 #define IPDSFIELD_CE_MASK 0x01
269 /* IP TOS, superseded by the DS Field, RFC 2474. */
270 #define IPTOS_TOS_MASK 0x1E
271 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
272 #define IPTOS_NONE 0x00
273 #define IPTOS_LOWCOST 0x02
274 #define IPTOS_RELIABILITY 0x04
275 #define IPTOS_THROUGHPUT 0x08
276 #define IPTOS_LOWDELAY 0x10
277 #define IPTOS_SECURITY 0x1E
279 #define IPTOS_PREC_MASK 0xE0
280 #define IPTOS_PREC_SHIFT 5
281 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
282 #define IPTOS_PREC_NETCONTROL 7
283 #define IPTOS_PREC_INTERNETCONTROL 6
284 #define IPTOS_PREC_CRITIC_ECP 5
285 #define IPTOS_PREC_FLASHOVERRIDE 4
286 #define IPTOS_PREC_FLASH 3
287 #define IPTOS_PREC_IMMEDIATE 2
288 #define IPTOS_PREC_PRIORITY 1
289 #define IPTOS_PREC_ROUTINE 0
292 #define IPOPT_COPY 0x80
294 #define IPOPT_CONTROL 0x00
295 #define IPOPT_RESERVED1 0x20
296 #define IPOPT_MEASUREMENT 0x40
297 #define IPOPT_RESERVED2 0x60
299 #define IPOPT_END (0 |IPOPT_CONTROL)
300 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
301 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
302 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
303 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
304 #define IPOPT_RR (7 |IPOPT_CONTROL)
305 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
306 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
307 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
309 /* IP option lengths */
310 #define IPOLEN_SEC 11
311 #define IPOLEN_LSRR_MIN 3
312 #define IPOLEN_TIMESTAMP_MIN 5
313 #define IPOLEN_RR_MIN 3
315 #define IPOLEN_SSRR_MIN 3
318 #define IPSEC_UNCLASSIFIED 0x0000
319 #define IPSEC_CONFIDENTIAL 0xF135
320 #define IPSEC_EFTO 0x789A
321 #define IPSEC_MMMM 0xBC4D
322 #define IPSEC_RESTRICTED 0xAF13
323 #define IPSEC_SECRET 0xD788
324 #define IPSEC_TOPSECRET 0x6BC5
325 #define IPSEC_RESERVED1 0x35E2
326 #define IPSEC_RESERVED2 0x9AF1
327 #define IPSEC_RESERVED3 0x4D78
328 #define IPSEC_RESERVED4 0x24BD
329 #define IPSEC_RESERVED5 0x135E
330 #define IPSEC_RESERVED6 0x89AF
331 #define IPSEC_RESERVED7 0xC4D6
332 #define IPSEC_RESERVED8 0xE26B
334 #define IPOPT_TS_TSONLY 0 /* timestamps only */
335 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
336 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
339 * defragmentation of IPv4
341 static GHashTable *ip_fragment_table = NULL;
344 ip_defragment_init(void)
346 fragment_table_init(&ip_fragment_table);
350 capture_ip(const u_char *pd, int offset, int len, packet_counts *ld) {
351 if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
355 switch (pd[offset + 9]) {
383 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
384 guint optlen, packet_info *pinfo _U_,
385 proto_tree *opt_tree)
387 proto_tree *field_tree = NULL;
390 static const value_string secl_vals[] = {
391 {IPSEC_UNCLASSIFIED, "Unclassified"},
392 {IPSEC_CONFIDENTIAL, "Confidential"},
393 {IPSEC_EFTO, "EFTO" },
394 {IPSEC_MMMM, "MMMM" },
395 {IPSEC_RESTRICTED, "Restricted" },
396 {IPSEC_SECRET, "Secret" },
397 {IPSEC_TOPSECRET, "Top secret" },
398 {IPSEC_RESERVED1, "Reserved" },
399 {IPSEC_RESERVED2, "Reserved" },
400 {IPSEC_RESERVED3, "Reserved" },
401 {IPSEC_RESERVED4, "Reserved" },
402 {IPSEC_RESERVED5, "Reserved" },
403 {IPSEC_RESERVED6, "Reserved" },
404 {IPSEC_RESERVED7, "Reserved" },
405 {IPSEC_RESERVED8, "Reserved" },
408 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
409 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
412 val = tvb_get_ntohs(tvb, offset);
413 proto_tree_add_text(field_tree, tvb, offset, 2,
414 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
417 val = tvb_get_ntohs(tvb, offset);
418 proto_tree_add_text(field_tree, tvb, offset, 2,
419 "Compartments: %u", val);
422 proto_tree_add_text(field_tree, tvb, offset, 2,
423 "Handling restrictions: %c%c",
424 tvb_get_guint8(tvb, offset),
425 tvb_get_guint8(tvb, offset + 1));
428 proto_tree_add_text(field_tree, tvb, offset, 3,
429 "Transmission control code: %c%c%c",
430 tvb_get_guint8(tvb, offset),
431 tvb_get_guint8(tvb, offset + 1),
432 tvb_get_guint8(tvb, offset + 2));
436 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
437 guint optlen, packet_info *pinfo _U_,
438 proto_tree *opt_tree)
440 proto_tree *field_tree = NULL;
446 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
448 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
450 optoffset += 2; /* skip past type and length */
451 optlen -= 2; /* subtract size of type and length */
453 ptr = tvb_get_guint8(tvb, offset + optoffset);
454 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
455 "Pointer: %d%s", ptr,
456 ((ptr < 4) ? " (points before first address)" :
457 ((ptr & 3) ? " (points to middle of address)" : "")));
460 ptr--; /* ptr is 1-origin */
464 proto_tree_add_text(field_tree, tvb, offset, optlen,
465 "(suboption would go past end of option)");
469 /* Avoids alignment problems on many architectures. */
470 tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
472 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
474 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
475 ((optoffset == ptr) ? " <- (current)" : ""));
482 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
483 guint optlen, packet_info *pinfo _U_,
484 proto_tree *opt_tree)
486 proto_tree_add_text(opt_tree, tvb, offset, optlen,
487 "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
492 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
493 int offset, guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
495 proto_tree *field_tree = NULL;
500 static const value_string flag_vals[] = {
501 {IPOPT_TS_TSONLY, "Time stamps only" },
502 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
503 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
508 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
509 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
511 optoffset += 2; /* skip past type and length */
512 optlen -= 2; /* subtract size of type and length */
514 ptr = tvb_get_guint8(tvb, offset + optoffset);
515 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
516 "Pointer: %d%s", ptr,
517 ((ptr < 5) ? " (points before first address)" :
518 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
521 ptr--; /* ptr is 1-origin */
523 flg = tvb_get_guint8(tvb, offset + optoffset);
524 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
525 "Overflow: %u", flg >> 4);
527 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
528 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
533 if (flg == IPOPT_TS_TSANDADDR) {
535 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
536 "(suboption would go past end of option)");
539 tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
540 ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
542 proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
543 "Address = %s, time stamp = %u",
544 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
549 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
550 "(suboption would go past end of option)");
553 ts = tvb_get_ntohl(tvb, offset + optoffset);
555 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
556 "Time stamp = %u", ts);
563 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
564 guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
566 /* Router-Alert, as defined by RFC2113 */
567 int opt = tvb_get_ntohs(tvb, offset + 2);
568 static const value_string ra_opts[] = {
569 {0, "Every router examines packet"},
573 proto_tree_add_text(opt_tree, tvb, offset, optlen,
574 "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
578 static const ip_tcp_opt ipopts[] = {
601 dissect_ipopt_security
605 "Strict source route",
606 &ett_ip_option_route,
613 "Loose source route",
614 &ett_ip_option_route,
622 &ett_ip_option_route,
638 &ett_ip_option_timestamp,
640 IPOLEN_TIMESTAMP_MIN,
641 dissect_ipopt_timestamp
653 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
655 /* Dissect the IP or TCP options in a packet. */
657 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
658 const ip_tcp_opt *opttab, int nopts, int eol,
659 packet_info *pinfo, proto_tree *opt_tree)
662 const ip_tcp_opt *optp;
663 opt_len_type len_type;
666 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
667 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
668 int, guint, packet_info *, proto_tree *);
672 opt = tvb_get_guint8(tvb, offset);
673 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
674 if (optp->optcode == opt)
677 if (optp == &opttab[nopts]) {
678 /* We assume that the only NO_LENGTH options are EOL and NOP options,
679 so that we can treat unknown options as VARIABLE_LENGTH with a
680 minimum of 2, and at least be able to move on to the next option
681 by using the length in the option. */
682 optp = NULL; /* indicate that we don't know this option */
683 len_type = VARIABLE_LENGTH;
685 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
689 len_type = optp->len_type;
690 optlen = optp->optlen;
692 dissect = optp->dissect;
694 --length; /* account for type byte */
695 if (len_type != NO_LENGTH) {
696 /* Option has a length. Is it in the packet? */
698 /* Bogus - packet must at least include option code byte and
700 proto_tree_add_text(opt_tree, tvb, offset, 1,
701 "%s (length byte past end of options)", name);
704 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
705 --length; /* account for length byte */
707 /* Bogus - option length is too short to include option code and
709 proto_tree_add_text(opt_tree, tvb, offset, 2,
710 "%s (with too-short option length = %u byte%s)", name,
711 len, plurality(len, "", "s"));
713 } else if (len - 2 > length) {
714 /* Bogus - option goes past the end of the header. */
715 proto_tree_add_text(opt_tree, tvb, offset, length,
716 "%s (option length = %u byte%s says option goes past end of options)",
717 name, len, plurality(len, "", "s"));
719 } else if (len_type == FIXED_LENGTH && len != optlen) {
720 /* Bogus - option length isn't what it's supposed to be for this
722 proto_tree_add_text(opt_tree, tvb, offset, len,
723 "%s (with option length = %u byte%s; should be %u)", name,
724 len, plurality(len, "", "s"), optlen);
726 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
727 /* Bogus - option length is less than what it's supposed to be for
729 proto_tree_add_text(opt_tree, tvb, offset, len,
730 "%s (with option length = %u byte%s; should be >= %u)", name,
731 len, plurality(len, "", "s"), optlen);
735 proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
736 name, len, plurality(len, "", "s"));
738 if (dissect != NULL) {
739 /* Option has a dissector. */
740 (*dissect)(optp, tvb, offset, len, pinfo, opt_tree);
742 /* Option has no data, hence no dissector. */
743 proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
746 len -= 2; /* subtract size of type and length */
751 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
759 const value_string dscp_vals[] = {
760 { IPDSFIELD_DSCP_DEFAULT, "Default" },
761 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
762 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
763 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
764 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
765 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
766 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
767 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
768 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
769 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
770 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
771 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
772 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
773 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
774 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
775 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
776 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
777 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
778 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
779 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
780 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
783 static const value_string precedence_vals[] = {
784 { IPTOS_PREC_ROUTINE, "routine" },
785 { IPTOS_PREC_PRIORITY, "priority" },
786 { IPTOS_PREC_IMMEDIATE, "immediate" },
787 { IPTOS_PREC_FLASH, "flash" },
788 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
789 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
790 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
791 { IPTOS_PREC_NETCONTROL, "network control" },
794 static const value_string iptos_vals[] = {
795 { IPTOS_NONE, "None" },
796 { IPTOS_LOWCOST, "Minimize cost" },
797 { IPTOS_RELIABILITY, "Maximize reliability" },
798 { IPTOS_THROUGHPUT, "Maximize throughput" },
799 { IPTOS_LOWDELAY, "Minimize delay" },
800 { IPTOS_SECURITY, "Maximize security" },
804 static const true_false_string tos_set_low = {
809 static const true_false_string tos_set_high = {
814 static const true_false_string flags_set_truth = {
819 static guint16 ip_checksum(const guint8 *ptr, int len)
823 cksum_vec[0].ptr = ptr;
824 cksum_vec[0].len = len;
825 return in_cksum(&cksum_vec[0], 1);
829 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
832 proto_tree *ip_tree = NULL, *field_tree;
835 guint hlen, optlen, len;
839 fragment_data *ipfd_head;
841 gboolean update_col_info = TRUE;
842 gboolean save_fragmented;
844 if (check_col(pinfo->cinfo, COL_PROTOCOL))
845 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
846 if (check_col(pinfo->cinfo, COL_INFO))
847 col_clear(pinfo->cinfo, COL_INFO);
849 /* Avoids alignment problems on many architectures. */
850 tvb_memcpy(tvb, (guint8 *)&iph, offset, sizeof(e_ip));
851 iph.ip_len = g_ntohs(iph.ip_len);
852 iph.ip_id = g_ntohs(iph.ip_id);
853 iph.ip_off = g_ntohs(iph.ip_off);
854 iph.ip_sum = g_ntohs(iph.ip_sum);
856 /* Length of IP datagram.
857 XXX - what if this is greater than the reported length of the
858 tvbuff? This could happen, for example, in an IP datagram
859 inside an ICMP datagram; we need to somehow let the
860 dissector we call know that, as it might want to avoid
861 doing its checksumming. */
864 /* Adjust the length of this tvbuff to include only the IP datagram. */
865 set_actual_length(tvb, len);
867 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
870 if (ip_summary_in_tree && hlen >= IPH_MIN_LEN) {
871 ti = proto_tree_add_protocol_format(tree, proto_ip, tvb, offset, hlen,
872 "Internet Protocol, Src Addr: %s (%s), Dst Addr: %s (%s)",
873 get_hostname(iph.ip_src), ip_to_str((guint8 *) &iph.ip_src),
874 get_hostname(iph.ip_dst), ip_to_str((guint8 *) &iph.ip_dst));
876 ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
878 ip_tree = proto_item_add_subtree(ti, ett_ip);
881 if (hlen < IPH_MIN_LEN) {
882 if (check_col(pinfo->cinfo, COL_INFO))
883 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
886 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
887 "Header length: %u bytes (bogus, must be at least %u)", hlen,
894 * Compute the checksum of the IP header.
896 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
899 proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1, hi_nibble(iph.ip_v_hl));
900 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
901 "Header length: %u bytes", hlen);
903 if (g_ip_dscp_actif) {
904 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph.ip_tos,
905 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph.ip_tos,
906 IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
907 "Unknown DSCP"),IPDSFIELD_ECN(iph.ip_tos));
909 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
910 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph.ip_tos);
911 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph.ip_tos);
912 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph.ip_tos);
914 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph.ip_tos,
915 "Type of service: 0x%02x (%s)", iph.ip_tos,
916 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
918 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
919 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph.ip_tos);
920 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph.ip_tos);
921 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph.ip_tos);
922 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph.ip_tos);
923 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph.ip_tos);
925 proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph.ip_len);
926 proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph.ip_id);
928 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
929 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
930 field_tree = proto_item_add_subtree(tf, ett_ip_off);
931 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
932 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
934 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
935 (iph.ip_off & IP_OFFSET)*8);
937 proto_tree_add_uint(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, iph.ip_ttl);
938 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph.ip_p,
939 "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
942 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
943 "Header checksum: 0x%04x (correct)", iph.ip_sum);
946 proto_tree_add_boolean_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
947 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
948 "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph.ip_sum,
949 in_cksum_shouldbe(iph.ip_sum, ipsum));
952 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, iph.ip_src);
953 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, iph.ip_dst);
954 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, iph.ip_src);
955 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, iph.ip_dst);
957 /* Decode IP options, if any. */
958 if (hlen > sizeof (e_ip)) {
959 /* There's more than just the fixed-length header. Decode the
961 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
962 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
963 "Options: (%u bytes)", optlen);
964 field_tree = proto_item_add_subtree(tf, ett_ip_options);
965 dissect_ip_tcp_options(tvb, offset + 20, optlen,
966 ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
970 pinfo->ipproto = iph.ip_p;
972 pinfo->iplen = iph.ip_len;
974 pinfo->iphdrlen = lo_nibble(iph.ip_v_hl);
976 SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
977 SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
978 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
979 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
981 /* Skip over header + options */
983 nxt = iph.ip_p; /* XXX - what if this isn't the same for all fragments? */
985 /* If ip_defragment is on, this is a fragment, we have all the data
986 * in the fragment, and the header checksum is valid, then just add
987 * the fragment to the hashtable.
989 save_fragmented = pinfo->fragmented;
990 if (ip_defragment && (iph.ip_off & (IP_MF|IP_OFFSET)) &&
991 tvb_reported_length(tvb) <= tvb_length(tvb) && ipsum == 0) {
992 ipfd_head = fragment_add(tvb, offset, pinfo, iph.ip_id,
994 (iph.ip_off & IP_OFFSET)*8,
995 pinfo->iplen - (pinfo->iphdrlen*4),
998 if (ipfd_head != NULL) {
999 /* OK, we have the complete reassembled payload.
1000 Allocate a new tvbuff, referring to the reassembled payload. */
1001 next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen,
1002 ipfd_head->datalen);
1004 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
1005 were handed refers, so it'll get cleaned up when that tvbuff
1007 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1009 /* Add the defragmented data to the data source list. */
1010 add_new_data_source(pinfo, next_tvb, "Reassembled IPv4");
1012 /* show all fragments */
1013 update_col_info = !show_fragment_tree(ipfd_head, &ip_frag_items,
1014 ip_tree, pinfo, next_tvb);
1016 /* We don't have the complete reassembled payload. */
1020 /* If this is the first fragment, dissect its contents, otherwise
1021 just show it as a fragment.
1023 XXX - if we eventually don't save the reassembled contents of all
1024 fragmented datagrams, we may want to always reassemble. */
1025 if (iph.ip_off & IP_OFFSET) {
1026 /* Not the first fragment - don't dissect it. */
1029 /* First fragment, or not fragmented. Dissect what we have here. */
1031 /* Get a tvbuff for the payload. */
1032 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1035 * If this is the first fragment, but not the only fragment,
1036 * tell the next protocol that.
1038 if (iph.ip_off & IP_MF)
1039 pinfo->fragmented = TRUE;
1041 pinfo->fragmented = FALSE;
1045 if (next_tvb == NULL) {
1046 /* Just show this as a fragment. */
1047 if (check_col(pinfo->cinfo, COL_INFO))
1048 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1049 ipprotostr(iph.ip_p), iph.ip_p, (iph.ip_off & IP_OFFSET) * 8);
1050 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
1052 pinfo->fragmented = save_fragmented;
1056 /* Hand off to the next protocol.
1058 XXX - setting the columns only after trying various dissectors means
1059 that if one of those dissectors throws an exception, the frame won't
1060 even be labelled as an IP frame; ideally, if a frame being dissected
1061 throws an exception, it'll be labelled as a mangled frame of the
1062 type in question. */
1063 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
1064 /* Unknown protocol */
1065 if (update_col_info) {
1066 if (check_col(pinfo->cinfo, COL_INFO))
1067 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
1069 call_dissector(data_handle,next_tvb, pinfo, tree);
1071 pinfo->fragmented = save_fragmented;
1074 #define ICMP_MIP_EXTENSION_PAD 0
1075 #define ICMP_MIP_MOB_AGENT_ADV 16
1076 #define ICMP_MIP_PREFIX_LENGTHS 19
1077 #define ICMP_MIP_CHALLENGE 24
1079 static value_string mip_extensions[] = {
1080 { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
1081 { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1083 { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
1084 { ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
1089 * Dissect the mobile ip advertisement extensions.
1092 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1098 proto_tree *mip_tree=NULL;
1099 proto_tree *flags_tree=NULL;
1103 /* Not much to do if we're not parsing everything */
1106 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1108 type = tvb_get_guint8(tvb, offset + 0);
1110 length = tvb_get_guint8(tvb, offset + 1);
1114 ti = proto_tree_add_text(tree, tvb, offset,
1115 type?(length + 2):1,
1117 val_to_str(type, mip_extensions,
1119 mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1123 case ICMP_MIP_EXTENSION_PAD:
1124 /* One byte padding extension */
1125 /* Add our fields */
1127 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1131 case ICMP_MIP_MOB_AGENT_ADV:
1132 /* Mobility Agent Advertisement Extension (RFC 2002)*/
1133 /* Add our fields */
1135 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1139 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1142 /* sequence number */
1143 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset,
1146 /* Registration Lifetime */
1147 proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset,
1151 flags = tvb_get_guint8(tvb, offset);
1152 ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1154 flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1155 proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1156 proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1157 proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1158 proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1159 proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1160 proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1161 proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1162 proto_tree_add_boolean(flags_tree, hf_icmp_mip_res, tvb, offset, 1, flags);
1166 proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset,
1171 numCOAs = (length - 6) / 4;
1172 for (i=0; i<numCOAs; i++) {
1173 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset,
1178 case ICMP_MIP_PREFIX_LENGTHS:
1179 /* Prefix-Lengths Extension (RFC 2002)*/
1180 /* Add our fields */
1182 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1186 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1190 /* prefix lengths */
1191 for(i=0; i<length; i++) {
1192 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1197 case ICMP_MIP_CHALLENGE:
1198 /* Challenge Extension (RFC 3012)*/
1200 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1204 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1208 proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset,
1214 g_warning("Unknown type(%u)! I hope the length is right (%u)",
1216 offset += length + 2;
1221 } /* dissect_mip_extensions */
1223 static const gchar *unreach_str[] = {"Network unreachable",
1225 "Protocol unreachable",
1227 "Fragmentation needed",
1228 "Source route failed",
1229 "Destination network unknown",
1230 "Destination host unknown",
1231 "Source host isolated",
1232 "Network administratively prohibited",
1233 "Host administratively prohibited",
1234 "Network unreachable for TOS",
1235 "Host unreachable for TOS",
1236 "Communication administratively filtered",
1237 "Host precedence violation",
1238 "Precedence cutoff in effect"};
1240 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1242 static const gchar *redir_str[] = {"Redirect for network",
1243 "Redirect for host",
1244 "Redirect for TOS and network",
1245 "Redirect for TOS and host"};
1247 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1249 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
1250 "TTL equals 0 during reassembly"};
1252 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1254 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1256 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1259 * RFC 792 for basic ICMP.
1260 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1261 * RFC 1256 for router discovery messages.
1262 * RFC 2002 and 3012 for Mobile IP stuff.
1265 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1267 proto_tree *icmp_tree;
1271 guint length, reported_length;
1272 guint16 cksum, computed_cksum;
1273 gchar type_str[64], code_str[64] = "";
1274 guint8 num_addrs = 0;
1275 guint8 addr_entry_size = 0;
1277 volatile address save_dl_src;
1278 volatile address save_dl_dst;
1279 volatile address save_net_src;
1280 volatile address save_net_dst;
1281 volatile address save_src;
1282 volatile address save_dst;
1283 gboolean save_in_error_pkt;
1286 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1287 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1288 if (check_col(pinfo->cinfo, COL_INFO))
1289 col_clear(pinfo->cinfo, COL_INFO);
1291 /* To do: check for runts, errs, etc. */
1292 icmp_type = tvb_get_guint8(tvb, 0);
1293 icmp_code = tvb_get_guint8(tvb, 1);
1294 cksum = tvb_get_ntohs(tvb, 2);
1296 switch (icmp_type) {
1297 case ICMP_ECHOREPLY:
1298 strcpy(type_str, "Echo (ping) reply");
1301 strcpy(type_str, "Destination unreachable");
1302 if (icmp_code < N_UNREACH) {
1303 sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1305 strcpy(code_str, "(Unknown - error?)");
1308 case ICMP_SOURCEQUENCH:
1309 strcpy(type_str, "Source quench (flow control)");
1312 strcpy(type_str, "Redirect");
1313 if (icmp_code < N_REDIRECT) {
1314 sprintf(code_str, "(%s)", redir_str[icmp_code]);
1316 strcpy(code_str, "(Unknown - error?)");
1320 strcpy(type_str, "Echo (ping) request");
1322 case ICMP_RTRADVERT:
1323 switch (icmp_code) {
1324 case 16: /* Mobile-Ip */
1325 strcpy(type_str, "Mobile IP Advertisement");
1328 strcpy(type_str, "Router advertisement");
1330 } /* switch icmp_code */
1332 case ICMP_RTRSOLICIT:
1333 strcpy(type_str, "Router solicitation");
1336 strcpy(type_str, "Time-to-live exceeded");
1337 if (icmp_code < N_TIMXCEED) {
1338 sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1340 strcpy(code_str, "(Unknown - error?)");
1343 case ICMP_PARAMPROB:
1344 strcpy(type_str, "Parameter problem");
1345 if (icmp_code < N_PARAMPROB) {
1346 sprintf(code_str, "(%s)", par_str[icmp_code]);
1348 strcpy(code_str, "(Unknown - error?)");
1352 strcpy(type_str, "Timestamp request");
1354 case ICMP_TSTAMPREPLY:
1355 strcpy(type_str, "Timestamp reply");
1358 strcpy(type_str, "Information request");
1360 case ICMP_IREQREPLY:
1361 strcpy(type_str, "Information reply");
1364 strcpy(type_str, "Address mask request");
1366 case ICMP_MASKREPLY:
1367 strcpy(type_str, "Address mask reply");
1370 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1374 if (check_col(pinfo->cinfo, COL_INFO))
1375 col_add_str(pinfo->cinfo, COL_INFO, type_str);
1378 length = tvb_length(tvb);
1379 reported_length = tvb_reported_length(tvb);
1380 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1381 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1382 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1385 icmp_type, type_str);
1386 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1389 icmp_code, code_str);
1391 if (!pinfo->fragmented && length >= reported_length) {
1392 /* The packet isn't part of a fragmented datagram and isn't
1393 truncated, so we can checksum it. */
1395 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1397 if (computed_cksum == 0) {
1398 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1400 "Checksum: 0x%04x (correct)", cksum);
1402 proto_tree_add_boolean_hidden(icmp_tree, hf_icmp_checksum_bad,
1404 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1406 "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1407 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1410 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1413 /* Decode the second 4 bytes of the packet. */
1414 switch (icmp_type) {
1415 case ICMP_ECHOREPLY:
1418 case ICMP_TSTAMPREPLY:
1420 case ICMP_IREQREPLY:
1422 case ICMP_MASKREPLY:
1423 proto_tree_add_text(icmp_tree, tvb, 4, 2, "Identifier: 0x%04x",
1424 tvb_get_ntohs(tvb, 4));
1425 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Sequence number: %02x:%02x",
1426 tvb_get_guint8(tvb, 6), tvb_get_guint8(tvb, 7));
1430 switch (icmp_code) {
1431 case ICMP_FRAG_NEEDED:
1432 proto_tree_add_text(icmp_tree, tvb, 6, 2, "MTU of next hop: %u",
1433 tvb_get_ntohs(tvb, 6));
1438 case ICMP_RTRADVERT:
1439 num_addrs = tvb_get_guint8(tvb, 4);
1440 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1442 addr_entry_size = tvb_get_guint8(tvb, 5);
1443 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1445 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1446 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1449 case ICMP_PARAMPROB:
1450 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1451 tvb_get_guint8(tvb, 4));
1455 proto_tree_add_text(icmp_tree, tvb, 4, 4, "Gateway address: %s",
1456 ip_to_str(tvb_get_ptr(tvb, 4, 4)));
1460 /* Decode the additional information in the packet. */
1461 switch (icmp_type) {
1464 case ICMP_PARAMPROB:
1465 case ICMP_SOURCEQUENCH:
1467 /* Decode the IP header and first 64 bits of data from the
1470 Set the columns non-writable, so that the packet list
1471 shows this as an ICMP packet, not as the type of packet
1472 for which the ICMP packet was generated. */
1473 col_set_writable(pinfo->cinfo, FALSE);
1475 /* Also, save the current values of the addresses, and restore
1476 them when we're finished dissecting the contained packet, so
1477 that the address columns in the summary don't reflect the
1478 contained packet, but reflect this packet instead. */
1479 save_dl_src = pinfo->dl_src;
1480 save_dl_dst = pinfo->dl_dst;
1481 save_net_src = pinfo->net_src;
1482 save_net_dst = pinfo->net_dst;
1483 save_src = pinfo->src;
1484 save_dst = pinfo->dst;
1486 /* Save the current value of the "we're inside an error packet"
1487 flag, and set that flag; subdissectors may treat packets
1488 that are the payload of error packets differently from
1490 save_in_error_pkt = pinfo->in_error_pkt;
1491 pinfo->in_error_pkt = TRUE;
1493 /* Dissect the contained packet.
1494 Catch ReportedBoundsError, and do nothing if we see it,
1495 because it's not an error if the contained packet is short;
1496 there's no guarantee that all of it was included.
1498 XXX - should catch BoundsError, and re-throw it after cleaning
1500 next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1502 call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1504 CATCH(ReportedBoundsError) {
1509 /* Restore the "we're inside an error packet" flag. */
1510 pinfo->in_error_pkt = save_in_error_pkt;
1512 /* Restore the addresses. */
1513 pinfo->dl_src = save_dl_src;
1514 pinfo->dl_dst = save_dl_dst;
1515 pinfo->net_src = save_net_src;
1516 pinfo->net_dst = save_net_dst;
1517 pinfo->src = save_src;
1518 pinfo->dst = save_dst;
1521 case ICMP_ECHOREPLY:
1523 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1527 case ICMP_RTRADVERT:
1528 if (addr_entry_size == 2) {
1529 for (i = 0; i < num_addrs; i++) {
1530 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1531 "Router address: %s",
1532 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1533 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1534 "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1536 if (icmp_code == 16) {
1538 dissect_mip_extensions(tvb, 8 + i*8, icmp_tree);
1541 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1546 case ICMP_TSTAMPREPLY:
1547 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1548 tvb_get_ntohl(tvb, 8));
1549 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1550 tvb_get_ntohl(tvb, 12));
1551 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1552 tvb_get_ntohl(tvb, 16));
1556 case ICMP_MASKREPLY:
1557 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1558 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1565 proto_register_ip(void)
1567 static hf_register_info hf[] = {
1570 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1574 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1578 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1581 { &hf_ip_dsfield_dscp,
1582 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1583 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1586 { &hf_ip_dsfield_ect,
1587 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1591 { &hf_ip_dsfield_ce,
1592 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1597 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1600 { &hf_ip_tos_precedence,
1601 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1606 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1610 { &hf_ip_tos_throughput,
1611 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1615 { &hf_ip_tos_reliability,
1616 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1621 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1626 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1630 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1634 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1638 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1642 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1646 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1650 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1654 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1657 { &hf_ip_frag_offset,
1658 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1662 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1666 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1670 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1673 { &hf_ip_checksum_bad,
1674 { "Bad Header checksum", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1677 { &hf_ip_fragment_overlap,
1678 { "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1679 "Fragment overlaps with other fragments", HFILL }},
1681 { &hf_ip_fragment_overlap_conflict,
1682 { "Conflicting data in fragment overlap", "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1683 "Overlapping fragments contained conflicting data", HFILL }},
1685 { &hf_ip_fragment_multiple_tails,
1686 { "Multiple tail fragments found", "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1687 "Several tails were found when defragmenting the packet", HFILL }},
1689 { &hf_ip_fragment_too_long_fragment,
1690 { "Fragment too long", "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1691 "Fragment contained data past end of packet", HFILL }},
1693 { &hf_ip_fragment_error,
1694 { "Defragmentation error", "ip.fragment.error", FT_NONE, BASE_NONE, NULL, 0x0,
1695 "Defragmentation error due to illegal fragments", HFILL }},
1698 { "IP Fragment", "ip.fragment", FT_NONE, BASE_NONE, NULL, 0x0,
1699 "IP Fragment", HFILL }},
1702 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1703 "IP Fragments", HFILL }},
1705 static gint *ett[] = {
1712 &ett_ip_option_route,
1713 &ett_ip_option_timestamp,
1717 module_t *ip_module;
1719 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1720 proto_register_field_array(proto_ip, hf, array_length(hf));
1721 proto_register_subtree_array(ett, array_length(ett));
1723 /* subdissector code */
1724 ip_dissector_table = register_dissector_table("ip.proto",
1725 "IP protocol", FT_UINT8, BASE_DEC);
1727 /* Register configuration options */
1728 ip_module = prefs_register_protocol(proto_ip, NULL);
1729 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1730 "Decode IPv4 TOS field as DiffServ field",
1731 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1733 prefs_register_bool_preference(ip_module, "defragment",
1734 "Reassemble fragmented IP datagrams",
1735 "Whether fragmented IP datagrams should be reassembled",
1737 prefs_register_bool_preference(ip_module, "ip_summary_in_tree",
1738 "Show IP summary in protocol tree",
1739 "Whether the IP summary line should be shown in the protocol tree",
1740 &ip_summary_in_tree);
1742 register_dissector("ip", dissect_ip, proto_ip);
1743 register_init_routine(ip_defragment_init);
1747 proto_reg_handoff_ip(void)
1749 dissector_handle_t ip_handle;
1751 data_handle = find_dissector("data");
1752 ip_handle = find_dissector("ip");
1753 dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
1754 dissector_add("ppp.protocol", PPP_IP, ip_handle);
1755 dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
1756 dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
1757 dissector_add("gre.proto", GRE_WCCP, ip_handle);
1758 dissector_add("llc.dsap", SAP_IP, ip_handle);
1759 dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
1760 dissector_add("null.type", BSD_AF_INET, ip_handle);
1761 dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
1762 dissector_add("fr.ietf", NLPID_IP, ip_handle);
1763 dissector_add("x.25.spi", NLPID_IP, ip_handle);
1767 proto_register_icmp(void)
1769 static hf_register_info hf[] = {
1772 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1776 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1779 { &hf_icmp_checksum,
1780 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1783 { &hf_icmp_checksum_bad,
1784 { "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1787 { &hf_icmp_mip_type,
1788 { "Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
1789 VALS(mip_extensions), 0x0,"", HFILL}},
1791 { &hf_icmp_mip_length,
1792 { "Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL, 0x0,
1795 { &hf_icmp_mip_prefix_length,
1796 { "Prefix Length", "icmp.mip.prefixlength", FT_UINT8, BASE_DEC, NULL, 0x0,
1800 { "Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC, NULL, 0x0,
1803 { &hf_icmp_mip_life,
1804 { "Registration Lifetime", "icmp.mip.life", FT_UINT16, BASE_DEC, NULL, 0x0,
1807 { &hf_icmp_mip_flags,
1808 { "Flags", "icmp.mip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1812 { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
1813 "Registration with this FA is required", HFILL }},
1816 { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
1817 "This FA will not accept requests at this time", HFILL }},
1820 { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
1821 "Home Agent Services Offered", HFILL }},
1824 { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
1825 "Foreign Agent Services Offered", HFILL }},
1828 { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
1829 "Minimal encapsulation tunneled datagram support", HFILL }},
1832 { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
1833 "GRE encapsulated tunneled datagram support", HFILL }},
1836 { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
1837 "Van Jacobson Header Compression Support", HFILL }},
1840 { "Reserved", "icmp.mip.res", FT_BOOLEAN, 8, NULL, 1,
1841 "Reserved", HFILL }},
1843 { &hf_icmp_mip_reserved,
1844 { "Reserved", "icmp.mip.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
1848 { "Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE, NULL, 0x0,
1851 { &hf_icmp_mip_challenge,
1852 { "Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE, NULL, 0x0,
1855 static gint *ett[] = {
1861 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
1863 proto_register_field_array(proto_icmp, hf, array_length(hf));
1864 proto_register_subtree_array(ett, array_length(ett));
1868 proto_reg_handoff_icmp(void)
1870 dissector_handle_t icmp_handle;
1873 * Get handle for the IP dissector.
1875 ip_handle = find_dissector("ip");
1877 icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
1878 dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);