2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.203 2004/04/19 23:36:46 obiot 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 if (flags & (IP_DF>>12)) proto_item_append_text(tf, " (Don't Fragment)");
936 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags);
937 if (flags & (IP_MF>>12)) proto_item_append_text(tf, " (More Fragments)");
938 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags);
940 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
941 (iph->ip_off & IP_OFFSET)*8);
945 proto_tree_add_item(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, FALSE);
947 iph->ip_p = tvb_get_guint8(tvb, offset + 9);
949 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph->ip_p,
950 "Protocol: %s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
953 iph->ip_sum = tvb_get_ntohs(tvb, offset + 10);
956 * If we have the entire IP header available, check the checksum.
958 if (tvb_bytes_exist(tvb, offset, hlen)) {
959 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
962 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
963 "Header checksum: 0x%04x (correct)", iph->ip_sum);
966 proto_tree_add_boolean_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
967 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
968 "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph->ip_sum,
969 in_cksum_shouldbe(iph->ip_sum, ipsum));
975 proto_tree_add_uint(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum);
978 SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
979 SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
980 SET_ADDRESS(&iph->ip_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
982 memcpy(&addr, iph->ip_src.data, 4);
983 if (ip_summary_in_tree) {
984 proto_item_append_text(ti, ", Src Addr: %s (%s)",
985 get_hostname(addr), ip_to_str((guint8 *) iph->ip_src.data));
987 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, addr);
988 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, addr);
991 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
992 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
993 SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
996 memcpy(&addr, iph->ip_dst.data, 4);
997 if (ip_summary_in_tree) {
998 proto_item_append_text(ti, ", Dst Addr: %s (%s)",
999 get_hostname(addr), ip_to_str((guint8 *) iph->ip_dst.data));
1001 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, addr);
1002 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, addr);
1006 /* Decode IP options, if any. */
1007 if (hlen > IPH_MIN_LEN) {
1008 /* There's more than just the fixed-length header. Decode the
1010 optlen = hlen - IPH_MIN_LEN; /* length of options, in bytes */
1011 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
1012 "Options: (%u bytes)", optlen);
1013 field_tree = proto_item_add_subtree(tf, ett_ip_options);
1014 dissect_ip_tcp_options(tvb, offset + 20, optlen,
1015 ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
1019 pinfo->ipproto = iph->ip_p;
1021 pinfo->iplen = iph->ip_len;
1023 pinfo->iphdrlen = hlen;
1025 /* Skip over header + options */
1027 nxt = iph->ip_p; /* XXX - what if this isn't the same for all fragments? */
1029 /* If ip_defragment is on, this is a fragment, we have all the data
1030 * in the fragment, and the header checksum is valid, then just add
1031 * the fragment to the hashtable.
1033 save_fragmented = pinfo->fragmented;
1034 if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
1035 tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
1037 ipfd_head = fragment_add_check(tvb, offset, pinfo, iph->ip_id,
1039 ip_reassembled_table,
1040 (iph->ip_off & IP_OFFSET)*8,
1041 pinfo->iplen - pinfo->iphdrlen,
1042 iph->ip_off & IP_MF);
1044 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv4",
1045 ipfd_head, &ip_frag_items, &update_col_info, ip_tree);
1047 /* If this is the first fragment, dissect its contents, otherwise
1048 just show it as a fragment.
1050 XXX - if we eventually don't save the reassembled contents of all
1051 fragmented datagrams, we may want to always reassemble. */
1052 if (iph->ip_off & IP_OFFSET) {
1053 /* Not the first fragment - don't dissect it. */
1056 /* First fragment, or not fragmented. Dissect what we have here. */
1058 /* Get a tvbuff for the payload. */
1059 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1062 * If this is the first fragment, but not the only fragment,
1063 * tell the next protocol that.
1065 if (iph->ip_off & IP_MF)
1066 pinfo->fragmented = TRUE;
1068 pinfo->fragmented = FALSE;
1072 if (next_tvb == NULL) {
1073 /* Just show this as a fragment. */
1074 if (check_col(pinfo->cinfo, COL_INFO)) {
1075 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1076 ipprotostr(iph->ip_p), iph->ip_p, (iph->ip_off & IP_OFFSET) * 8);
1078 if( ipfd_head && ipfd_head->reassembled_in != pinfo->fd->num ){
1079 if (check_col(pinfo->cinfo, COL_INFO)) {
1080 col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]",
1081 ipfd_head->reassembled_in);
1085 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
1087 pinfo->fragmented = save_fragmented;
1091 /* Hand off to the next protocol.
1093 XXX - setting the columns only after trying various dissectors means
1094 that if one of those dissectors throws an exception, the frame won't
1095 even be labelled as an IP frame; ideally, if a frame being dissected
1096 throws an exception, it'll be labelled as a mangled frame of the
1097 type in question. */
1098 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
1099 /* Unknown protocol */
1100 if (update_col_info) {
1101 if (check_col(pinfo->cinfo, COL_INFO))
1102 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
1104 call_dissector(data_handle,next_tvb, pinfo, tree);
1106 pinfo->fragmented = save_fragmented;
1109 tap_queue_packet(ip_tap, pinfo, iph);
1113 #define ICMP_MIP_EXTENSION_PAD 0
1114 #define ICMP_MIP_MOB_AGENT_ADV 16
1115 #define ICMP_MIP_PREFIX_LENGTHS 19
1116 #define ICMP_MIP_CHALLENGE 24
1118 static value_string mip_extensions[] = {
1119 { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
1120 { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1122 { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
1123 { ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
1128 * Dissect the mobile ip advertisement extensions.
1131 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1137 proto_tree *mip_tree=NULL;
1138 proto_tree *flags_tree=NULL;
1142 /* Not much to do if we're not parsing everything */
1145 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1147 type = tvb_get_guint8(tvb, offset + 0);
1149 length = tvb_get_guint8(tvb, offset + 1);
1153 ti = proto_tree_add_text(tree, tvb, offset,
1154 type?(length + 2):1,
1156 val_to_str(type, mip_extensions,
1158 mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1162 case ICMP_MIP_EXTENSION_PAD:
1163 /* One byte padding extension */
1164 /* Add our fields */
1166 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1170 case ICMP_MIP_MOB_AGENT_ADV:
1171 /* Mobility Agent Advertisement Extension (RFC 2002)*/
1172 /* Add our fields */
1174 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1178 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1181 /* sequence number */
1182 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset,
1185 /* Registration Lifetime */
1186 proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset,
1190 flags = tvb_get_guint8(tvb, offset);
1191 ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1193 flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1194 proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1195 proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1196 proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1197 proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1198 proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1199 proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1200 proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1201 proto_tree_add_boolean(flags_tree, hf_icmp_mip_res, tvb, offset, 1, flags);
1205 proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset,
1210 numCOAs = (length - 6) / 4;
1211 for (i=0; i<numCOAs; i++) {
1212 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset,
1217 case ICMP_MIP_PREFIX_LENGTHS:
1218 /* Prefix-Lengths Extension (RFC 2002)*/
1219 /* Add our fields */
1221 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1225 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1229 /* prefix lengths */
1230 for(i=0; i<length; i++) {
1231 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1236 case ICMP_MIP_CHALLENGE:
1237 /* Challenge Extension (RFC 3012)*/
1239 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1243 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1247 proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset,
1253 g_warning("Unknown type(%u)! I hope the length is right (%u)",
1255 offset += length + 2;
1260 } /* dissect_mip_extensions */
1262 static const gchar *unreach_str[] = {"Network unreachable",
1264 "Protocol unreachable",
1266 "Fragmentation needed",
1267 "Source route failed",
1268 "Destination network unknown",
1269 "Destination host unknown",
1270 "Source host isolated",
1271 "Network administratively prohibited",
1272 "Host administratively prohibited",
1273 "Network unreachable for TOS",
1274 "Host unreachable for TOS",
1275 "Communication administratively filtered",
1276 "Host precedence violation",
1277 "Precedence cutoff in effect"};
1279 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1281 static const gchar *redir_str[] = {"Redirect for network",
1282 "Redirect for host",
1283 "Redirect for TOS and network",
1284 "Redirect for TOS and host"};
1286 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1288 static const gchar *ttl_str[] = {"Time to live exceeded in transit",
1289 "Fragment reassembly time exceeded"};
1291 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1293 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1295 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1298 * RFC 792 for basic ICMP.
1299 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1300 * RFC 1256 for router discovery messages.
1301 * RFC 2002 and 3012 for Mobile IP stuff.
1304 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1306 proto_tree *icmp_tree;
1310 guint length, reported_length;
1311 guint16 cksum, computed_cksum;
1312 gchar type_str[64], code_str[64] = "";
1313 guint8 num_addrs = 0;
1314 guint8 addr_entry_size = 0;
1316 gboolean save_in_error_pkt;
1319 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1320 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1321 if (check_col(pinfo->cinfo, COL_INFO))
1322 col_clear(pinfo->cinfo, COL_INFO);
1324 /* To do: check for runts, errs, etc. */
1325 icmp_type = tvb_get_guint8(tvb, 0);
1326 icmp_code = tvb_get_guint8(tvb, 1);
1327 cksum = tvb_get_ntohs(tvb, 2);
1329 switch (icmp_type) {
1330 case ICMP_ECHOREPLY:
1331 strcpy(type_str, "Echo (ping) reply");
1334 strcpy(type_str, "Destination unreachable");
1335 if (icmp_code < N_UNREACH) {
1336 sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1338 strcpy(code_str, "(Unknown - error?)");
1341 case ICMP_SOURCEQUENCH:
1342 strcpy(type_str, "Source quench (flow control)");
1345 strcpy(type_str, "Redirect");
1346 if (icmp_code < N_REDIRECT) {
1347 sprintf(code_str, "(%s)", redir_str[icmp_code]);
1349 strcpy(code_str, "(Unknown - error?)");
1353 strcpy(type_str, "Echo (ping) request");
1355 case ICMP_RTRADVERT:
1356 switch (icmp_code) {
1357 case 16: /* Mobile-Ip */
1358 strcpy(type_str, "Mobile IP Advertisement");
1361 strcpy(type_str, "Router advertisement");
1363 } /* switch icmp_code */
1365 case ICMP_RTRSOLICIT:
1366 strcpy(type_str, "Router solicitation");
1369 strcpy(type_str, "Time-to-live exceeded");
1370 if (icmp_code < N_TIMXCEED) {
1371 sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1373 strcpy(code_str, "(Unknown - error?)");
1376 case ICMP_PARAMPROB:
1377 strcpy(type_str, "Parameter problem");
1378 if (icmp_code < N_PARAMPROB) {
1379 sprintf(code_str, "(%s)", par_str[icmp_code]);
1381 strcpy(code_str, "(Unknown - error?)");
1385 strcpy(type_str, "Timestamp request");
1387 case ICMP_TSTAMPREPLY:
1388 strcpy(type_str, "Timestamp reply");
1391 strcpy(type_str, "Information request");
1393 case ICMP_IREQREPLY:
1394 strcpy(type_str, "Information reply");
1397 strcpy(type_str, "Address mask request");
1399 case ICMP_MASKREPLY:
1400 strcpy(type_str, "Address mask reply");
1403 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1407 if (check_col(pinfo->cinfo, COL_INFO))
1408 col_add_str(pinfo->cinfo, COL_INFO, type_str);
1411 length = tvb_length(tvb);
1412 reported_length = tvb_reported_length(tvb);
1413 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1414 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1415 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1418 icmp_type, type_str);
1419 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1422 icmp_code, code_str);
1424 if (!pinfo->fragmented && length >= reported_length) {
1425 /* The packet isn't part of a fragmented datagram and isn't
1426 truncated, so we can checksum it. */
1428 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1430 if (computed_cksum == 0) {
1431 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1433 "Checksum: 0x%04x (correct)", cksum);
1435 proto_tree_add_boolean_hidden(icmp_tree, hf_icmp_checksum_bad,
1437 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1439 "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1440 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1443 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1446 /* Decode the second 4 bytes of the packet. */
1447 switch (icmp_type) {
1448 case ICMP_ECHOREPLY:
1451 case ICMP_TSTAMPREPLY:
1453 case ICMP_IREQREPLY:
1455 case ICMP_MASKREPLY:
1456 proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, FALSE);
1457 proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2, FALSE);
1461 switch (icmp_code) {
1462 case ICMP_FRAG_NEEDED:
1463 proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6, 2, FALSE);
1468 case ICMP_RTRADVERT:
1469 num_addrs = tvb_get_guint8(tvb, 4);
1470 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1472 addr_entry_size = tvb_get_guint8(tvb, 5);
1473 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1475 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1476 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1479 case ICMP_PARAMPROB:
1480 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1481 tvb_get_guint8(tvb, 4));
1485 proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4, FALSE);
1489 /* Decode the additional information in the packet. */
1490 switch (icmp_type) {
1493 case ICMP_PARAMPROB:
1494 case ICMP_SOURCEQUENCH:
1496 /* Save the current value of the "we're inside an error packet"
1497 flag, and set that flag; subdissectors may treat packets
1498 that are the payload of error packets differently from
1500 save_in_error_pkt = pinfo->in_error_pkt;
1501 pinfo->in_error_pkt = TRUE;
1503 /* Decode the IP header and first 64 bits of data from the
1504 original datagram. */
1505 next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1506 call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1508 /* Restore the "we're inside an error packet" flag. */
1509 pinfo->in_error_pkt = save_in_error_pkt;
1512 case ICMP_ECHOREPLY:
1514 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1518 case ICMP_RTRADVERT:
1519 if (addr_entry_size == 2) {
1520 for (i = 0; i < num_addrs; i++) {
1521 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1522 "Router address: %s",
1523 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1524 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1525 "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1527 if (icmp_code == 16) {
1529 dissect_mip_extensions(tvb, 8 + i*8, icmp_tree);
1532 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1537 case ICMP_TSTAMPREPLY:
1538 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1539 tvb_get_ntohl(tvb, 8));
1540 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1541 tvb_get_ntohl(tvb, 12));
1542 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1543 tvb_get_ntohl(tvb, 16));
1547 case ICMP_MASKREPLY:
1548 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1549 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1556 proto_register_ip(void)
1558 static hf_register_info hf[] = {
1561 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1565 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1569 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1572 { &hf_ip_dsfield_dscp,
1573 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1574 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1577 { &hf_ip_dsfield_ect,
1578 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1582 { &hf_ip_dsfield_ce,
1583 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1588 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1591 { &hf_ip_tos_precedence,
1592 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1597 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1601 { &hf_ip_tos_throughput,
1602 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1606 { &hf_ip_tos_reliability,
1607 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1612 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1617 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1621 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1625 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1629 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1633 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1637 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1641 { "Reserved bit", "ip.flags.rb", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_RF >> 12,
1645 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF >> 12,
1649 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF >> 12,
1652 { &hf_ip_frag_offset,
1653 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1657 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1661 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1665 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1668 { &hf_ip_checksum_bad,
1669 { "Bad Header checksum", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1672 { &hf_ip_fragment_overlap,
1673 { "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1674 "Fragment overlaps with other fragments", HFILL }},
1676 { &hf_ip_fragment_overlap_conflict,
1677 { "Conflicting data in fragment overlap", "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1678 "Overlapping fragments contained conflicting data", HFILL }},
1680 { &hf_ip_fragment_multiple_tails,
1681 { "Multiple tail fragments found", "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1682 "Several tails were found when defragmenting the packet", HFILL }},
1684 { &hf_ip_fragment_too_long_fragment,
1685 { "Fragment too long", "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1686 "Fragment contained data past end of packet", HFILL }},
1688 { &hf_ip_fragment_error,
1689 { "Defragmentation error", "ip.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1690 "Defragmentation error due to illegal fragments", HFILL }},
1693 { "IP Fragment", "ip.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1694 "IP Fragment", HFILL }},
1697 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1698 "IP Fragments", HFILL }},
1700 { &hf_ip_reassembled_in,
1701 { "Reassembled IP in frame", "ip.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1702 "This IP packet is reassembled in this frame", HFILL }}
1704 static gint *ett[] = {
1711 &ett_ip_option_route,
1712 &ett_ip_option_timestamp,
1716 module_t *ip_module;
1718 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1719 proto_register_field_array(proto_ip, hf, array_length(hf));
1720 proto_register_subtree_array(ett, array_length(ett));
1722 /* subdissector code */
1723 ip_dissector_table = register_dissector_table("ip.proto",
1724 "IP protocol", FT_UINT8, BASE_DEC);
1726 /* Register configuration options */
1727 ip_module = prefs_register_protocol(proto_ip, NULL);
1728 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1729 "Decode IPv4 TOS field as DiffServ field",
1730 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1732 prefs_register_bool_preference(ip_module, "defragment",
1733 "Reassemble fragmented IP datagrams",
1734 "Whether fragmented IP datagrams should be reassembled",
1736 prefs_register_bool_preference(ip_module, "summary_in_tree",
1737 "Show IP summary in protocol tree",
1738 "Whether the IP summary line should be shown in the protocol tree",
1739 &ip_summary_in_tree);
1741 register_dissector("ip", dissect_ip, proto_ip);
1742 register_init_routine(ip_defragment_init);
1743 ip_tap=register_tap("ip");
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);
1764 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1051, ip_handle);
1765 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1201, ip_handle);
1769 proto_register_icmp(void)
1771 static hf_register_info hf[] = {
1774 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1778 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1781 { &hf_icmp_checksum,
1782 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1785 { &hf_icmp_checksum_bad,
1786 { "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1790 {"Identifier", "icmp.ident", FT_UINT16, BASE_HEX, NULL, 0x0,
1794 {"Sequence number", "icmp.seq", FT_UINT16, BASE_HEX, NULL, 0x0,
1798 {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL, 0x0,
1801 { &hf_icmp_redir_gw,
1802 {"Gateway address", "icmp.redir_gw", FT_IPv4, BASE_NONE, NULL, 0x0,
1805 { &hf_icmp_mip_type,
1806 { "Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
1807 VALS(mip_extensions), 0x0,"", HFILL}},
1809 { &hf_icmp_mip_length,
1810 { "Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL, 0x0,
1813 { &hf_icmp_mip_prefix_length,
1814 { "Prefix Length", "icmp.mip.prefixlength", FT_UINT8, BASE_DEC, NULL, 0x0,
1818 { "Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC, NULL, 0x0,
1821 { &hf_icmp_mip_life,
1822 { "Registration Lifetime", "icmp.mip.life", FT_UINT16, BASE_DEC, NULL, 0x0,
1825 { &hf_icmp_mip_flags,
1826 { "Flags", "icmp.mip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1830 { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
1831 "Registration with this FA is required", HFILL }},
1834 { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
1835 "This FA will not accept requests at this time", HFILL }},
1838 { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
1839 "Home Agent Services Offered", HFILL }},
1842 { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
1843 "Foreign Agent Services Offered", HFILL }},
1846 { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
1847 "Minimal encapsulation tunneled datagram support", HFILL }},
1850 { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
1851 "GRE encapsulated tunneled datagram support", HFILL }},
1854 { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
1855 "Van Jacobson Header Compression Support", HFILL }},
1858 { "Reserved", "icmp.mip.res", FT_BOOLEAN, 8, NULL, 1,
1859 "Reserved", HFILL }},
1861 { &hf_icmp_mip_reserved,
1862 { "Reserved", "icmp.mip.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
1866 { "Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE, NULL, 0x0,
1869 { &hf_icmp_mip_challenge,
1870 { "Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE, NULL, 0x0,
1873 static gint *ett[] = {
1879 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
1881 proto_register_field_array(proto_icmp, hf, array_length(hf));
1882 proto_register_subtree_array(ett, array_length(ett));
1886 proto_reg_handoff_icmp(void)
1888 dissector_handle_t icmp_handle;
1891 * Get handle for the IP dissector.
1893 ip_handle = find_dissector("ip");
1895 icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
1896 dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);