2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.202 2004/02/18 06:43:00 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.
33 #ifdef NEED_SNPRINTF_H
34 # include "snprintf.h"
37 #include <epan/packet.h>
38 #include <epan/resolv.h>
42 #include "reassemble.h"
48 #include "arcnet_pids.h"
49 #include "packet-ip.h"
50 #include "packet-ipsec.h"
55 static int ip_tap = -1;
57 static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
59 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
60 static gboolean g_ip_dscp_actif = TRUE;
62 /* Defragment fragmented IP datagrams */
63 static gboolean ip_defragment = FALSE;
65 /* Place IP summary in proto tree */
66 static gboolean ip_summary_in_tree = TRUE;
68 static int proto_ip = -1;
69 static int hf_ip_version = -1;
70 static int hf_ip_hdr_len = -1;
71 static int hf_ip_dsfield = -1;
72 static int hf_ip_dsfield_dscp = -1;
73 static int hf_ip_dsfield_ect = -1;
74 static int hf_ip_dsfield_ce = -1;
75 static int hf_ip_tos = -1;
76 static int hf_ip_tos_precedence = -1;
77 static int hf_ip_tos_delay = -1;
78 static int hf_ip_tos_throughput = -1;
79 static int hf_ip_tos_reliability = -1;
80 static int hf_ip_tos_cost = -1;
81 static int hf_ip_len = -1;
82 static int hf_ip_id = -1;
83 static int hf_ip_dst = -1;
84 static int hf_ip_src = -1;
85 static int hf_ip_addr = -1;
86 static int hf_ip_flags = -1;
87 static int hf_ip_flags_rf = -1;
88 static int hf_ip_flags_df = -1;
89 static int hf_ip_flags_mf = -1;
90 static int hf_ip_frag_offset = -1;
91 static int hf_ip_ttl = -1;
92 static int hf_ip_proto = -1;
93 static int hf_ip_checksum = -1;
94 static int hf_ip_checksum_bad = -1;
95 static int hf_ip_fragments = -1;
96 static int hf_ip_fragment = -1;
97 static int hf_ip_fragment_overlap = -1;
98 static int hf_ip_fragment_overlap_conflict = -1;
99 static int hf_ip_fragment_multiple_tails = -1;
100 static int hf_ip_fragment_too_long_fragment = -1;
101 static int hf_ip_fragment_error = -1;
102 static int hf_ip_reassembled_in = -1;
104 static gint ett_ip = -1;
105 static gint ett_ip_dsfield = -1;
106 static gint ett_ip_tos = -1;
107 static gint ett_ip_off = -1;
108 static gint ett_ip_options = -1;
109 static gint ett_ip_option_sec = -1;
110 static gint ett_ip_option_route = -1;
111 static gint ett_ip_option_timestamp = -1;
112 static gint ett_ip_fragments = -1;
113 static gint ett_ip_fragment = -1;
115 static const fragment_items ip_frag_items = {
120 &hf_ip_fragment_overlap,
121 &hf_ip_fragment_overlap_conflict,
122 &hf_ip_fragment_multiple_tails,
123 &hf_ip_fragment_too_long_fragment,
124 &hf_ip_fragment_error,
125 &hf_ip_reassembled_in,
129 static dissector_table_t ip_dissector_table;
131 static dissector_handle_t ip_handle;
132 static dissector_handle_t data_handle;
134 static int proto_icmp = -1;
135 static int hf_icmp_type = -1;
136 static int hf_icmp_code = -1;
137 static int hf_icmp_checksum = -1;
138 static int hf_icmp_checksum_bad = -1;
139 static int hf_icmp_ident = -1;
140 static int hf_icmp_seq_num = -1;
141 static int hf_icmp_mtu = -1;
142 static int hf_icmp_redir_gw = -1;
146 static int hf_icmp_mip_type = -1;
147 static int hf_icmp_mip_length = -1;
148 static int hf_icmp_mip_prefix_length = -1;
149 static int hf_icmp_mip_seq = -1;
150 static int hf_icmp_mip_life = -1;
151 static int hf_icmp_mip_flags = -1;
152 static int hf_icmp_mip_r = -1;
153 static int hf_icmp_mip_b = -1;
154 static int hf_icmp_mip_h = -1;
155 static int hf_icmp_mip_f = -1;
156 static int hf_icmp_mip_m = -1;
157 static int hf_icmp_mip_g = -1;
158 static int hf_icmp_mip_v = -1;
159 static int hf_icmp_mip_res = -1;
160 static int hf_icmp_mip_reserved = -1;
161 static int hf_icmp_mip_coa = -1;
162 static int hf_icmp_mip_challenge = -1;
164 static gint ett_icmp = -1;
165 static gint ett_icmp_mip = -1;
166 static gint ett_icmp_mip_flags = -1;
168 /* ICMP definitions */
170 #define ICMP_ECHOREPLY 0
171 #define ICMP_UNREACH 3
172 #define ICMP_SOURCEQUENCH 4
173 #define ICMP_REDIRECT 5
175 #define ICMP_RTRADVERT 9
176 #define ICMP_RTRSOLICIT 10
177 #define ICMP_TIMXCEED 11
178 #define ICMP_PARAMPROB 12
179 #define ICMP_TSTAMP 13
180 #define ICMP_TSTAMPREPLY 14
182 #define ICMP_IREQREPLY 16
183 #define ICMP_MASKREQ 17
184 #define ICMP_MASKREPLY 18
186 /* ICMP UNREACHABLE */
188 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
189 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
190 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
191 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
192 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
193 #define ICMP_SR_FAILED 5 /* Source Route failed */
194 #define ICMP_NET_UNKNOWN 6
195 #define ICMP_HOST_UNKNOWN 7
196 #define ICMP_HOST_ISOLATED 8
197 #define ICMP_NET_ANO 9
198 #define ICMP_HOST_ANO 10
199 #define ICMP_NET_UNR_TOS 11
200 #define ICMP_HOST_UNR_TOS 12
201 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
202 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
203 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
206 /* IP structs and definitions */
208 /* Offsets of fields within an IP header. */
220 /* Minimum IP header length. */
221 #define IPH_MIN_LEN 20
224 #define IP_RF 0x8000 /* Flag: "Reserved bit" */
225 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
226 #define IP_MF 0x2000 /* Flag: "More Fragments" */
227 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
229 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
230 #define IPDSFIELD_DSCP_MASK 0xFC
231 #define IPDSFIELD_ECN_MASK 0x03
232 #define IPDSFIELD_DSCP_SHIFT 2
233 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
234 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
235 #define IPDSFIELD_DSCP_DEFAULT 0x00
236 #define IPDSFIELD_DSCP_CS1 0x08
237 #define IPDSFIELD_DSCP_CS2 0x10
238 #define IPDSFIELD_DSCP_CS3 0x18
239 #define IPDSFIELD_DSCP_CS4 0x20
240 #define IPDSFIELD_DSCP_CS5 0x28
241 #define IPDSFIELD_DSCP_CS6 0x30
242 #define IPDSFIELD_DSCP_CS7 0x38
243 #define IPDSFIELD_DSCP_AF11 0x0A
244 #define IPDSFIELD_DSCP_AF12 0x0C
245 #define IPDSFIELD_DSCP_AF13 0x0E
246 #define IPDSFIELD_DSCP_AF21 0x12
247 #define IPDSFIELD_DSCP_AF22 0x14
248 #define IPDSFIELD_DSCP_AF23 0x16
249 #define IPDSFIELD_DSCP_AF31 0x1A
250 #define IPDSFIELD_DSCP_AF32 0x1C
251 #define IPDSFIELD_DSCP_AF33 0x1E
252 #define IPDSFIELD_DSCP_AF41 0x22
253 #define IPDSFIELD_DSCP_AF42 0x24
254 #define IPDSFIELD_DSCP_AF43 0x26
255 #define IPDSFIELD_DSCP_EF 0x2E
256 #define IPDSFIELD_ECT_MASK 0x02
257 #define IPDSFIELD_CE_MASK 0x01
259 /* IP TOS, superseded by the DS Field, RFC 2474. */
260 #define IPTOS_TOS_MASK 0x1E
261 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
262 #define IPTOS_NONE 0x00
263 #define IPTOS_LOWCOST 0x02
264 #define IPTOS_RELIABILITY 0x04
265 #define IPTOS_THROUGHPUT 0x08
266 #define IPTOS_LOWDELAY 0x10
267 #define IPTOS_SECURITY 0x1E
269 #define IPTOS_PREC_MASK 0xE0
270 #define IPTOS_PREC_SHIFT 5
271 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
272 #define IPTOS_PREC_NETCONTROL 7
273 #define IPTOS_PREC_INTERNETCONTROL 6
274 #define IPTOS_PREC_CRITIC_ECP 5
275 #define IPTOS_PREC_FLASHOVERRIDE 4
276 #define IPTOS_PREC_FLASH 3
277 #define IPTOS_PREC_IMMEDIATE 2
278 #define IPTOS_PREC_PRIORITY 1
279 #define IPTOS_PREC_ROUTINE 0
282 #define IPOPT_COPY 0x80
284 #define IPOPT_CONTROL 0x00
285 #define IPOPT_RESERVED1 0x20
286 #define IPOPT_MEASUREMENT 0x40
287 #define IPOPT_RESERVED2 0x60
289 #define IPOPT_END (0 |IPOPT_CONTROL)
290 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
291 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
292 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
293 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
294 #define IPOPT_RR (7 |IPOPT_CONTROL)
295 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
296 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
297 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
299 /* IP option lengths */
300 #define IPOLEN_SEC 11
301 #define IPOLEN_LSRR_MIN 3
302 #define IPOLEN_TIMESTAMP_MIN 5
303 #define IPOLEN_RR_MIN 3
305 #define IPOLEN_SSRR_MIN 3
308 #define IPSEC_UNCLASSIFIED 0x0000
309 #define IPSEC_CONFIDENTIAL 0xF135
310 #define IPSEC_EFTO 0x789A
311 #define IPSEC_MMMM 0xBC4D
312 #define IPSEC_RESTRICTED 0xAF13
313 #define IPSEC_SECRET 0xD788
314 #define IPSEC_TOPSECRET 0x6BC5
315 #define IPSEC_RESERVED1 0x35E2
316 #define IPSEC_RESERVED2 0x9AF1
317 #define IPSEC_RESERVED3 0x4D78
318 #define IPSEC_RESERVED4 0x24BD
319 #define IPSEC_RESERVED5 0x135E
320 #define IPSEC_RESERVED6 0x89AF
321 #define IPSEC_RESERVED7 0xC4D6
322 #define IPSEC_RESERVED8 0xE26B
324 #define IPOPT_TS_TSONLY 0 /* timestamps only */
325 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
326 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
329 * defragmentation of IPv4
331 static GHashTable *ip_fragment_table = NULL;
332 static GHashTable *ip_reassembled_table = NULL;
335 ip_defragment_init(void)
337 fragment_table_init(&ip_fragment_table);
338 reassembled_table_init(&ip_reassembled_table);
342 capture_ip(const guchar *pd, int offset, int len, packet_counts *ld) {
343 if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
347 switch (pd[offset + 9]) {
358 case IP_PROTO_ICMPV6: /* XXX - separate counters? */
376 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
377 guint optlen, packet_info *pinfo _U_,
378 proto_tree *opt_tree)
380 proto_tree *field_tree = NULL;
383 static const value_string secl_vals[] = {
384 {IPSEC_UNCLASSIFIED, "Unclassified"},
385 {IPSEC_CONFIDENTIAL, "Confidential"},
386 {IPSEC_EFTO, "EFTO" },
387 {IPSEC_MMMM, "MMMM" },
388 {IPSEC_RESTRICTED, "Restricted" },
389 {IPSEC_SECRET, "Secret" },
390 {IPSEC_TOPSECRET, "Top secret" },
391 {IPSEC_RESERVED1, "Reserved" },
392 {IPSEC_RESERVED2, "Reserved" },
393 {IPSEC_RESERVED3, "Reserved" },
394 {IPSEC_RESERVED4, "Reserved" },
395 {IPSEC_RESERVED5, "Reserved" },
396 {IPSEC_RESERVED6, "Reserved" },
397 {IPSEC_RESERVED7, "Reserved" },
398 {IPSEC_RESERVED8, "Reserved" },
401 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
402 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
405 val = tvb_get_ntohs(tvb, offset);
406 proto_tree_add_text(field_tree, tvb, offset, 2,
407 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
410 val = tvb_get_ntohs(tvb, offset);
411 proto_tree_add_text(field_tree, tvb, offset, 2,
412 "Compartments: %u", val);
415 proto_tree_add_text(field_tree, tvb, offset, 2,
416 "Handling restrictions: %c%c",
417 tvb_get_guint8(tvb, offset),
418 tvb_get_guint8(tvb, offset + 1));
421 proto_tree_add_text(field_tree, tvb, offset, 3,
422 "Transmission control code: %c%c%c",
423 tvb_get_guint8(tvb, offset),
424 tvb_get_guint8(tvb, offset + 1),
425 tvb_get_guint8(tvb, offset + 2));
429 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
430 guint optlen, packet_info *pinfo _U_,
431 proto_tree *opt_tree)
433 proto_tree *field_tree = NULL;
439 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
441 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
443 optoffset += 2; /* skip past type and length */
444 optlen -= 2; /* subtract size of type and length */
446 ptr = tvb_get_guint8(tvb, offset + optoffset);
447 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
448 "Pointer: %d%s", ptr,
449 ((ptr < 4) ? " (points before first address)" :
450 ((ptr & 3) ? " (points to middle of address)" : "")));
453 ptr--; /* ptr is 1-origin */
457 proto_tree_add_text(field_tree, tvb, offset, optlen,
458 "(suboption would go past end of option)");
462 /* Avoids alignment problems on many architectures. */
463 tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
465 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
467 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
468 ((optoffset == ptr) ? " <- (current)" : ""));
475 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
476 guint optlen, packet_info *pinfo _U_,
477 proto_tree *opt_tree)
479 proto_tree_add_text(opt_tree, tvb, offset, optlen,
480 "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
485 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
486 int offset, guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
488 proto_tree *field_tree = NULL;
493 static const value_string flag_vals[] = {
494 {IPOPT_TS_TSONLY, "Time stamps only" },
495 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
496 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
501 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
502 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
504 optoffset += 2; /* skip past type and length */
505 optlen -= 2; /* subtract size of type and length */
507 ptr = tvb_get_guint8(tvb, offset + optoffset);
508 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
509 "Pointer: %d%s", ptr,
510 ((ptr < 5) ? " (points before first address)" :
511 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
514 ptr--; /* ptr is 1-origin */
516 flg = tvb_get_guint8(tvb, offset + optoffset);
517 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
518 "Overflow: %u", flg >> 4);
520 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
521 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
526 if (flg == IPOPT_TS_TSANDADDR) {
528 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
529 "(suboption would go past end of option)");
532 tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
533 ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
535 proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
536 "Address = %s, time stamp = %u",
537 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
542 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
543 "(suboption would go past end of option)");
546 ts = tvb_get_ntohl(tvb, offset + optoffset);
548 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
549 "Time stamp = %u", ts);
556 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
557 guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
559 /* Router-Alert, as defined by RFC2113 */
560 int opt = tvb_get_ntohs(tvb, offset + 2);
561 static const value_string ra_opts[] = {
562 {0, "Every router examines packet"},
566 proto_tree_add_text(opt_tree, tvb, offset, optlen,
567 "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
571 static const ip_tcp_opt ipopts[] = {
594 dissect_ipopt_security
598 "Strict source route",
599 &ett_ip_option_route,
606 "Loose source route",
607 &ett_ip_option_route,
615 &ett_ip_option_route,
631 &ett_ip_option_timestamp,
633 IPOLEN_TIMESTAMP_MIN,
634 dissect_ipopt_timestamp
646 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
648 /* Dissect the IP or TCP options in a packet. */
650 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
651 const ip_tcp_opt *opttab, int nopts, int eol,
652 packet_info *pinfo, proto_tree *opt_tree)
655 const ip_tcp_opt *optp;
656 opt_len_type len_type;
659 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
660 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
661 int, guint, packet_info *, proto_tree *);
665 opt = tvb_get_guint8(tvb, offset);
666 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
667 if (optp->optcode == opt)
670 if (optp == &opttab[nopts]) {
671 /* We assume that the only NO_LENGTH options are EOL and NOP options,
672 so that we can treat unknown options as VARIABLE_LENGTH with a
673 minimum of 2, and at least be able to move on to the next option
674 by using the length in the option. */
675 optp = NULL; /* indicate that we don't know this option */
676 len_type = VARIABLE_LENGTH;
678 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
682 len_type = optp->len_type;
683 optlen = optp->optlen;
685 dissect = optp->dissect;
687 --length; /* account for type byte */
688 if (len_type != NO_LENGTH) {
689 /* Option has a length. Is it in the packet? */
691 /* Bogus - packet must at least include option code byte and
693 proto_tree_add_text(opt_tree, tvb, offset, 1,
694 "%s (length byte past end of options)", name);
697 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
698 --length; /* account for length byte */
700 /* Bogus - option length is too short to include option code and
702 proto_tree_add_text(opt_tree, tvb, offset, 2,
703 "%s (with too-short option length = %u byte%s)", name,
704 len, plurality(len, "", "s"));
706 } else if (len - 2 > length) {
707 /* Bogus - option goes past the end of the header. */
708 proto_tree_add_text(opt_tree, tvb, offset, length,
709 "%s (option length = %u byte%s says option goes past end of options)",
710 name, len, plurality(len, "", "s"));
712 } else if (len_type == FIXED_LENGTH && len != optlen) {
713 /* Bogus - option length isn't what it's supposed to be for this
715 proto_tree_add_text(opt_tree, tvb, offset, len,
716 "%s (with option length = %u byte%s; should be %u)", name,
717 len, plurality(len, "", "s"), optlen);
719 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
720 /* Bogus - option length is less than what it's supposed to be for
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);
728 proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
729 name, len, plurality(len, "", "s"));
731 if (dissect != NULL) {
732 /* Option has a dissector. */
733 (*dissect)(optp, tvb, offset, len, pinfo, opt_tree);
735 /* Option has no data, hence no dissector. */
736 proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
739 len -= 2; /* subtract size of type and length */
744 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
752 const value_string dscp_vals[] = {
753 { IPDSFIELD_DSCP_DEFAULT, "Default" },
754 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
755 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
756 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
757 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
758 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
759 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
760 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
761 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
762 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
763 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
764 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
765 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
766 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
767 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
768 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
769 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
770 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
771 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
772 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
773 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
776 static const value_string precedence_vals[] = {
777 { IPTOS_PREC_ROUTINE, "routine" },
778 { IPTOS_PREC_PRIORITY, "priority" },
779 { IPTOS_PREC_IMMEDIATE, "immediate" },
780 { IPTOS_PREC_FLASH, "flash" },
781 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
782 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
783 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
784 { IPTOS_PREC_NETCONTROL, "network control" },
787 static const value_string iptos_vals[] = {
788 { IPTOS_NONE, "None" },
789 { IPTOS_LOWCOST, "Minimize cost" },
790 { IPTOS_RELIABILITY, "Maximize reliability" },
791 { IPTOS_THROUGHPUT, "Maximize throughput" },
792 { IPTOS_LOWDELAY, "Minimize delay" },
793 { IPTOS_SECURITY, "Maximize security" },
797 static const true_false_string tos_set_low = {
802 static const true_false_string tos_set_high = {
807 static guint16 ip_checksum(const guint8 *ptr, int len)
811 cksum_vec[0].ptr = ptr;
812 cksum_vec[0].len = len;
813 return in_cksum(&cksum_vec[0], 1);
817 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
819 proto_tree *ip_tree = NULL, *field_tree;
820 proto_item *ti = NULL, *tf;
827 fragment_data *ipfd_head=NULL;
829 gboolean update_col_info = TRUE;
830 gboolean save_fragmented;
831 static e_ip eip_arr[4];
832 static int eip_current=0;
839 iph=&eip_arr[eip_current];
841 if (check_col(pinfo->cinfo, COL_PROTOCOL))
842 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
843 if (check_col(pinfo->cinfo, COL_INFO))
844 col_clear(pinfo->cinfo, COL_INFO);
846 iph->ip_v_hl = tvb_get_guint8(tvb, offset);
847 hlen = lo_nibble(iph->ip_v_hl) * 4; /* IP header length, in bytes */
850 ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
851 ip_tree = proto_item_add_subtree(ti, ett_ip);
853 proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1,
854 hi_nibble(iph->ip_v_hl));
857 if (hlen < IPH_MIN_LEN) {
858 if (check_col(pinfo->cinfo, COL_INFO))
859 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
862 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
863 "Header length: %u bytes (bogus, must be at least %u)", hlen,
870 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
871 "Header length: %u bytes", hlen);
874 iph->ip_tos = tvb_get_guint8(tvb, offset + 1);
876 if (g_ip_dscp_actif) {
877 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph->ip_tos,
878 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph->ip_tos,
879 IPDSFIELD_DSCP(iph->ip_tos), val_to_str(IPDSFIELD_DSCP(iph->ip_tos), dscp_vals,
880 "Unknown DSCP"),IPDSFIELD_ECN(iph->ip_tos));
882 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
883 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph->ip_tos);
884 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph->ip_tos);
885 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph->ip_tos);
887 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph->ip_tos,
888 "Type of service: 0x%02x (%s)", iph->ip_tos,
889 val_to_str( IPTOS_TOS(iph->ip_tos), iptos_vals, "Unknown") );
891 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
892 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph->ip_tos);
893 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph->ip_tos);
894 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph->ip_tos);
895 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph->ip_tos);
896 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph->ip_tos);
900 /* Length of IP datagram.
901 XXX - what if this is greater than the reported length of the
902 tvbuff? This could happen, for example, in an IP datagram
903 inside an ICMP datagram; we need to somehow let the
904 dissector we call know that, as it might want to avoid
905 doing its checksumming. */
906 iph->ip_len = tvb_get_ntohs(tvb, offset + 2);
908 /* Adjust the length of this tvbuff to include only the IP datagram. */
909 set_actual_length(tvb, iph->ip_len);
911 if (iph->ip_len < hlen) {
912 if (check_col(pinfo->cinfo, COL_INFO))
913 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP length (%u, less than header length %u)",
916 proto_tree_add_uint_format(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len,
917 "Total length: %u bytes (bogus, less than header length %u)", iph->ip_len,
923 proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len);
925 iph->ip_id = tvb_get_ntohs(tvb, offset + 4);
927 proto_tree_add_uint_format(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph->ip_id, "Identification: 0x%04x (%d)", iph->ip_id, iph->ip_id);
929 iph->ip_off = tvb_get_ntohs(tvb, offset + 6);
931 flags = (iph->ip_off & (IP_RF | IP_DF | IP_MF)) >> 12;
932 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
933 field_tree = proto_item_add_subtree(tf, ett_ip_off);
934 proto_tree_add_boolean(field_tree, hf_ip_flags_rf, tvb, offset + 6, 1, flags);
935 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags);
936 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags);
938 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
939 (iph->ip_off & IP_OFFSET)*8);
943 proto_tree_add_item(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, FALSE);
945 iph->ip_p = tvb_get_guint8(tvb, offset + 9);
947 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph->ip_p,
948 "Protocol: %s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
951 iph->ip_sum = tvb_get_ntohs(tvb, offset + 10);
954 * If we have the entire IP header available, check the checksum.
956 if (tvb_bytes_exist(tvb, offset, hlen)) {
957 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
960 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
961 "Header checksum: 0x%04x (correct)", iph->ip_sum);
964 proto_tree_add_boolean_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
965 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
966 "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph->ip_sum,
967 in_cksum_shouldbe(iph->ip_sum, ipsum));
973 proto_tree_add_uint(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum);
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(&iph->ip_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
980 memcpy(&addr, iph->ip_src.data, 4);
981 if (ip_summary_in_tree) {
982 proto_item_append_text(ti, ", Src Addr: %s (%s)",
983 get_hostname(addr), ip_to_str((guint8 *) iph->ip_src.data));
985 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, addr);
986 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, addr);
989 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
990 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
991 SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
994 memcpy(&addr, iph->ip_dst.data, 4);
995 if (ip_summary_in_tree) {
996 proto_item_append_text(ti, ", Dst Addr: %s (%s)",
997 get_hostname(addr), ip_to_str((guint8 *) iph->ip_dst.data));
999 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, addr);
1000 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, addr);
1004 /* Decode IP options, if any. */
1005 if (hlen > IPH_MIN_LEN) {
1006 /* There's more than just the fixed-length header. Decode the
1008 optlen = hlen - IPH_MIN_LEN; /* length of options, in bytes */
1009 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
1010 "Options: (%u bytes)", optlen);
1011 field_tree = proto_item_add_subtree(tf, ett_ip_options);
1012 dissect_ip_tcp_options(tvb, offset + 20, optlen,
1013 ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
1017 pinfo->ipproto = iph->ip_p;
1019 pinfo->iplen = iph->ip_len;
1021 pinfo->iphdrlen = hlen;
1023 /* Skip over header + options */
1025 nxt = iph->ip_p; /* XXX - what if this isn't the same for all fragments? */
1027 /* If ip_defragment is on, this is a fragment, we have all the data
1028 * in the fragment, and the header checksum is valid, then just add
1029 * the fragment to the hashtable.
1031 save_fragmented = pinfo->fragmented;
1032 if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
1033 tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
1035 ipfd_head = fragment_add_check(tvb, offset, pinfo, iph->ip_id,
1037 ip_reassembled_table,
1038 (iph->ip_off & IP_OFFSET)*8,
1039 pinfo->iplen - pinfo->iphdrlen,
1040 iph->ip_off & IP_MF);
1042 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv4",
1043 ipfd_head, &ip_frag_items, &update_col_info, ip_tree);
1045 /* If this is the first fragment, dissect its contents, otherwise
1046 just show it as a fragment.
1048 XXX - if we eventually don't save the reassembled contents of all
1049 fragmented datagrams, we may want to always reassemble. */
1050 if (iph->ip_off & IP_OFFSET) {
1051 /* Not the first fragment - don't dissect it. */
1054 /* First fragment, or not fragmented. Dissect what we have here. */
1056 /* Get a tvbuff for the payload. */
1057 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1060 * If this is the first fragment, but not the only fragment,
1061 * tell the next protocol that.
1063 if (iph->ip_off & IP_MF)
1064 pinfo->fragmented = TRUE;
1066 pinfo->fragmented = FALSE;
1070 if (next_tvb == NULL) {
1071 /* Just show this as a fragment. */
1072 if (check_col(pinfo->cinfo, COL_INFO)) {
1073 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1074 ipprotostr(iph->ip_p), iph->ip_p, (iph->ip_off & IP_OFFSET) * 8);
1076 if( ipfd_head && ipfd_head->reassembled_in != pinfo->fd->num ){
1077 if (check_col(pinfo->cinfo, COL_INFO)) {
1078 col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]",
1079 ipfd_head->reassembled_in);
1083 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
1085 pinfo->fragmented = save_fragmented;
1089 /* Hand off to the next protocol.
1091 XXX - setting the columns only after trying various dissectors means
1092 that if one of those dissectors throws an exception, the frame won't
1093 even be labelled as an IP frame; ideally, if a frame being dissected
1094 throws an exception, it'll be labelled as a mangled frame of the
1095 type in question. */
1096 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
1097 /* Unknown protocol */
1098 if (update_col_info) {
1099 if (check_col(pinfo->cinfo, COL_INFO))
1100 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
1102 call_dissector(data_handle,next_tvb, pinfo, tree);
1104 pinfo->fragmented = save_fragmented;
1107 tap_queue_packet(ip_tap, pinfo, iph);
1111 #define ICMP_MIP_EXTENSION_PAD 0
1112 #define ICMP_MIP_MOB_AGENT_ADV 16
1113 #define ICMP_MIP_PREFIX_LENGTHS 19
1114 #define ICMP_MIP_CHALLENGE 24
1116 static value_string mip_extensions[] = {
1117 { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
1118 { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1120 { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
1121 { ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
1126 * Dissect the mobile ip advertisement extensions.
1129 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1135 proto_tree *mip_tree=NULL;
1136 proto_tree *flags_tree=NULL;
1140 /* Not much to do if we're not parsing everything */
1143 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1145 type = tvb_get_guint8(tvb, offset + 0);
1147 length = tvb_get_guint8(tvb, offset + 1);
1151 ti = proto_tree_add_text(tree, tvb, offset,
1152 type?(length + 2):1,
1154 val_to_str(type, mip_extensions,
1156 mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1160 case ICMP_MIP_EXTENSION_PAD:
1161 /* One byte padding extension */
1162 /* Add our fields */
1164 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1168 case ICMP_MIP_MOB_AGENT_ADV:
1169 /* Mobility Agent Advertisement Extension (RFC 2002)*/
1170 /* Add our fields */
1172 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1176 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1179 /* sequence number */
1180 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset,
1183 /* Registration Lifetime */
1184 proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset,
1188 flags = tvb_get_guint8(tvb, offset);
1189 ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1191 flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1192 proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1193 proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1194 proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1195 proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1196 proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1197 proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1198 proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1199 proto_tree_add_boolean(flags_tree, hf_icmp_mip_res, tvb, offset, 1, flags);
1203 proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset,
1208 numCOAs = (length - 6) / 4;
1209 for (i=0; i<numCOAs; i++) {
1210 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset,
1215 case ICMP_MIP_PREFIX_LENGTHS:
1216 /* Prefix-Lengths Extension (RFC 2002)*/
1217 /* Add our fields */
1219 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1223 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1227 /* prefix lengths */
1228 for(i=0; i<length; i++) {
1229 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1234 case ICMP_MIP_CHALLENGE:
1235 /* Challenge Extension (RFC 3012)*/
1237 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1241 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1245 proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset,
1251 g_warning("Unknown type(%u)! I hope the length is right (%u)",
1253 offset += length + 2;
1258 } /* dissect_mip_extensions */
1260 static const gchar *unreach_str[] = {"Network unreachable",
1262 "Protocol unreachable",
1264 "Fragmentation needed",
1265 "Source route failed",
1266 "Destination network unknown",
1267 "Destination host unknown",
1268 "Source host isolated",
1269 "Network administratively prohibited",
1270 "Host administratively prohibited",
1271 "Network unreachable for TOS",
1272 "Host unreachable for TOS",
1273 "Communication administratively filtered",
1274 "Host precedence violation",
1275 "Precedence cutoff in effect"};
1277 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1279 static const gchar *redir_str[] = {"Redirect for network",
1280 "Redirect for host",
1281 "Redirect for TOS and network",
1282 "Redirect for TOS and host"};
1284 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1286 static const gchar *ttl_str[] = {"Time to live exceeded in transit",
1287 "Fragment reassembly time exceeded"};
1289 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1291 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1293 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1296 * RFC 792 for basic ICMP.
1297 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1298 * RFC 1256 for router discovery messages.
1299 * RFC 2002 and 3012 for Mobile IP stuff.
1302 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1304 proto_tree *icmp_tree;
1308 guint length, reported_length;
1309 guint16 cksum, computed_cksum;
1310 gchar type_str[64], code_str[64] = "";
1311 guint8 num_addrs = 0;
1312 guint8 addr_entry_size = 0;
1314 gboolean save_in_error_pkt;
1317 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1318 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1319 if (check_col(pinfo->cinfo, COL_INFO))
1320 col_clear(pinfo->cinfo, COL_INFO);
1322 /* To do: check for runts, errs, etc. */
1323 icmp_type = tvb_get_guint8(tvb, 0);
1324 icmp_code = tvb_get_guint8(tvb, 1);
1325 cksum = tvb_get_ntohs(tvb, 2);
1327 switch (icmp_type) {
1328 case ICMP_ECHOREPLY:
1329 strcpy(type_str, "Echo (ping) reply");
1332 strcpy(type_str, "Destination unreachable");
1333 if (icmp_code < N_UNREACH) {
1334 sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1336 strcpy(code_str, "(Unknown - error?)");
1339 case ICMP_SOURCEQUENCH:
1340 strcpy(type_str, "Source quench (flow control)");
1343 strcpy(type_str, "Redirect");
1344 if (icmp_code < N_REDIRECT) {
1345 sprintf(code_str, "(%s)", redir_str[icmp_code]);
1347 strcpy(code_str, "(Unknown - error?)");
1351 strcpy(type_str, "Echo (ping) request");
1353 case ICMP_RTRADVERT:
1354 switch (icmp_code) {
1355 case 16: /* Mobile-Ip */
1356 strcpy(type_str, "Mobile IP Advertisement");
1359 strcpy(type_str, "Router advertisement");
1361 } /* switch icmp_code */
1363 case ICMP_RTRSOLICIT:
1364 strcpy(type_str, "Router solicitation");
1367 strcpy(type_str, "Time-to-live exceeded");
1368 if (icmp_code < N_TIMXCEED) {
1369 sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1371 strcpy(code_str, "(Unknown - error?)");
1374 case ICMP_PARAMPROB:
1375 strcpy(type_str, "Parameter problem");
1376 if (icmp_code < N_PARAMPROB) {
1377 sprintf(code_str, "(%s)", par_str[icmp_code]);
1379 strcpy(code_str, "(Unknown - error?)");
1383 strcpy(type_str, "Timestamp request");
1385 case ICMP_TSTAMPREPLY:
1386 strcpy(type_str, "Timestamp reply");
1389 strcpy(type_str, "Information request");
1391 case ICMP_IREQREPLY:
1392 strcpy(type_str, "Information reply");
1395 strcpy(type_str, "Address mask request");
1397 case ICMP_MASKREPLY:
1398 strcpy(type_str, "Address mask reply");
1401 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1405 if (check_col(pinfo->cinfo, COL_INFO))
1406 col_add_str(pinfo->cinfo, COL_INFO, type_str);
1409 length = tvb_length(tvb);
1410 reported_length = tvb_reported_length(tvb);
1411 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1412 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1413 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1416 icmp_type, type_str);
1417 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1420 icmp_code, code_str);
1422 if (!pinfo->fragmented && length >= reported_length) {
1423 /* The packet isn't part of a fragmented datagram and isn't
1424 truncated, so we can checksum it. */
1426 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1428 if (computed_cksum == 0) {
1429 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1431 "Checksum: 0x%04x (correct)", cksum);
1433 proto_tree_add_boolean_hidden(icmp_tree, hf_icmp_checksum_bad,
1435 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1437 "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1438 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1441 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1444 /* Decode the second 4 bytes of the packet. */
1445 switch (icmp_type) {
1446 case ICMP_ECHOREPLY:
1449 case ICMP_TSTAMPREPLY:
1451 case ICMP_IREQREPLY:
1453 case ICMP_MASKREPLY:
1454 proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, FALSE);
1455 proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2, FALSE);
1459 switch (icmp_code) {
1460 case ICMP_FRAG_NEEDED:
1461 proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6, 2, FALSE);
1466 case ICMP_RTRADVERT:
1467 num_addrs = tvb_get_guint8(tvb, 4);
1468 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1470 addr_entry_size = tvb_get_guint8(tvb, 5);
1471 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1473 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1474 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1477 case ICMP_PARAMPROB:
1478 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1479 tvb_get_guint8(tvb, 4));
1483 proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4, FALSE);
1487 /* Decode the additional information in the packet. */
1488 switch (icmp_type) {
1491 case ICMP_PARAMPROB:
1492 case ICMP_SOURCEQUENCH:
1494 /* Save the current value of the "we're inside an error packet"
1495 flag, and set that flag; subdissectors may treat packets
1496 that are the payload of error packets differently from
1498 save_in_error_pkt = pinfo->in_error_pkt;
1499 pinfo->in_error_pkt = TRUE;
1501 /* Decode the IP header and first 64 bits of data from the
1502 original datagram. */
1503 next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1504 call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1506 /* Restore the "we're inside an error packet" flag. */
1507 pinfo->in_error_pkt = save_in_error_pkt;
1510 case ICMP_ECHOREPLY:
1512 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1516 case ICMP_RTRADVERT:
1517 if (addr_entry_size == 2) {
1518 for (i = 0; i < num_addrs; i++) {
1519 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1520 "Router address: %s",
1521 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1522 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1523 "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1525 if (icmp_code == 16) {
1527 dissect_mip_extensions(tvb, 8 + i*8, icmp_tree);
1530 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1535 case ICMP_TSTAMPREPLY:
1536 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1537 tvb_get_ntohl(tvb, 8));
1538 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1539 tvb_get_ntohl(tvb, 12));
1540 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1541 tvb_get_ntohl(tvb, 16));
1545 case ICMP_MASKREPLY:
1546 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1547 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1554 proto_register_ip(void)
1556 static hf_register_info hf[] = {
1559 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1563 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1567 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1570 { &hf_ip_dsfield_dscp,
1571 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1572 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1575 { &hf_ip_dsfield_ect,
1576 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1580 { &hf_ip_dsfield_ce,
1581 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1586 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1589 { &hf_ip_tos_precedence,
1590 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1595 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1599 { &hf_ip_tos_throughput,
1600 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1604 { &hf_ip_tos_reliability,
1605 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1610 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1615 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1619 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1623 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1627 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1631 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1635 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1639 { "Reserved bit", "ip.flags.rb", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_RF >> 12,
1643 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF >> 12,
1647 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF >> 12,
1650 { &hf_ip_frag_offset,
1651 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1655 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1659 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1663 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1666 { &hf_ip_checksum_bad,
1667 { "Bad Header checksum", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1670 { &hf_ip_fragment_overlap,
1671 { "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1672 "Fragment overlaps with other fragments", HFILL }},
1674 { &hf_ip_fragment_overlap_conflict,
1675 { "Conflicting data in fragment overlap", "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1676 "Overlapping fragments contained conflicting data", HFILL }},
1678 { &hf_ip_fragment_multiple_tails,
1679 { "Multiple tail fragments found", "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1680 "Several tails were found when defragmenting the packet", HFILL }},
1682 { &hf_ip_fragment_too_long_fragment,
1683 { "Fragment too long", "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1684 "Fragment contained data past end of packet", HFILL }},
1686 { &hf_ip_fragment_error,
1687 { "Defragmentation error", "ip.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1688 "Defragmentation error due to illegal fragments", HFILL }},
1691 { "IP Fragment", "ip.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1692 "IP Fragment", HFILL }},
1695 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1696 "IP Fragments", HFILL }},
1698 { &hf_ip_reassembled_in,
1699 { "Reassembled IP in frame", "ip.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1700 "This IP packet is reassembled in this frame", HFILL }}
1702 static gint *ett[] = {
1709 &ett_ip_option_route,
1710 &ett_ip_option_timestamp,
1714 module_t *ip_module;
1716 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1717 proto_register_field_array(proto_ip, hf, array_length(hf));
1718 proto_register_subtree_array(ett, array_length(ett));
1720 /* subdissector code */
1721 ip_dissector_table = register_dissector_table("ip.proto",
1722 "IP protocol", FT_UINT8, BASE_DEC);
1724 /* Register configuration options */
1725 ip_module = prefs_register_protocol(proto_ip, NULL);
1726 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1727 "Decode IPv4 TOS field as DiffServ field",
1728 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1730 prefs_register_bool_preference(ip_module, "defragment",
1731 "Reassemble fragmented IP datagrams",
1732 "Whether fragmented IP datagrams should be reassembled",
1734 prefs_register_bool_preference(ip_module, "summary_in_tree",
1735 "Show IP summary in protocol tree",
1736 "Whether the IP summary line should be shown in the protocol tree",
1737 &ip_summary_in_tree);
1739 register_dissector("ip", dissect_ip, proto_ip);
1740 register_init_routine(ip_defragment_init);
1741 ip_tap=register_tap("ip");
1745 proto_reg_handoff_ip(void)
1747 dissector_handle_t ip_handle;
1749 data_handle = find_dissector("data");
1750 ip_handle = find_dissector("ip");
1751 dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
1752 dissector_add("ppp.protocol", PPP_IP, ip_handle);
1753 dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
1754 dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
1755 dissector_add("gre.proto", GRE_WCCP, ip_handle);
1756 dissector_add("llc.dsap", SAP_IP, ip_handle);
1757 dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
1758 dissector_add("null.type", BSD_AF_INET, ip_handle);
1759 dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
1760 dissector_add("fr.ietf", NLPID_IP, ip_handle);
1761 dissector_add("x.25.spi", NLPID_IP, ip_handle);
1762 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1051, ip_handle);
1763 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1201, 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,
1788 {"Identifier", "icmp.ident", FT_UINT16, BASE_HEX, NULL, 0x0,
1792 {"Sequence number", "icmp.seq", FT_UINT16, BASE_HEX, NULL, 0x0,
1796 {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL, 0x0,
1799 { &hf_icmp_redir_gw,
1800 {"Gateway address", "icmp.redir_gw", FT_IPv4, BASE_NONE, NULL, 0x0,
1803 { &hf_icmp_mip_type,
1804 { "Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
1805 VALS(mip_extensions), 0x0,"", HFILL}},
1807 { &hf_icmp_mip_length,
1808 { "Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL, 0x0,
1811 { &hf_icmp_mip_prefix_length,
1812 { "Prefix Length", "icmp.mip.prefixlength", FT_UINT8, BASE_DEC, NULL, 0x0,
1816 { "Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC, NULL, 0x0,
1819 { &hf_icmp_mip_life,
1820 { "Registration Lifetime", "icmp.mip.life", FT_UINT16, BASE_DEC, NULL, 0x0,
1823 { &hf_icmp_mip_flags,
1824 { "Flags", "icmp.mip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1828 { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
1829 "Registration with this FA is required", HFILL }},
1832 { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
1833 "This FA will not accept requests at this time", HFILL }},
1836 { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
1837 "Home Agent Services Offered", HFILL }},
1840 { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
1841 "Foreign Agent Services Offered", HFILL }},
1844 { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
1845 "Minimal encapsulation tunneled datagram support", HFILL }},
1848 { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
1849 "GRE encapsulated tunneled datagram support", HFILL }},
1852 { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
1853 "Van Jacobson Header Compression Support", HFILL }},
1856 { "Reserved", "icmp.mip.res", FT_BOOLEAN, 8, NULL, 1,
1857 "Reserved", HFILL }},
1859 { &hf_icmp_mip_reserved,
1860 { "Reserved", "icmp.mip.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
1864 { "Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE, NULL, 0x0,
1867 { &hf_icmp_mip_challenge,
1868 { "Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE, NULL, 0x0,
1871 static gint *ett[] = {
1877 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
1879 proto_register_field_array(proto_icmp, hf, array_length(hf));
1880 proto_register_subtree_array(ett, array_length(ett));
1884 proto_reg_handoff_icmp(void)
1886 dissector_handle_t icmp_handle;
1889 * Get handle for the IP dissector.
1891 ip_handle = find_dissector("ip");
1893 icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
1894 dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);