2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.199 2003/08/29 22:15:19 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_df = -1;
88 static int hf_ip_flags_mf = -1;
89 static int hf_ip_frag_offset = -1;
90 static int hf_ip_ttl = -1;
91 static int hf_ip_proto = -1;
92 static int hf_ip_checksum = -1;
93 static int hf_ip_checksum_bad = -1;
94 static int hf_ip_fragments = -1;
95 static int hf_ip_fragment = -1;
96 static int hf_ip_fragment_overlap = -1;
97 static int hf_ip_fragment_overlap_conflict = -1;
98 static int hf_ip_fragment_multiple_tails = -1;
99 static int hf_ip_fragment_too_long_fragment = -1;
100 static int hf_ip_fragment_error = -1;
101 static int hf_ip_reassembled_in = -1;
103 static gint ett_ip = -1;
104 static gint ett_ip_dsfield = -1;
105 static gint ett_ip_tos = -1;
106 static gint ett_ip_off = -1;
107 static gint ett_ip_options = -1;
108 static gint ett_ip_option_sec = -1;
109 static gint ett_ip_option_route = -1;
110 static gint ett_ip_option_timestamp = -1;
111 static gint ett_ip_fragments = -1;
112 static gint ett_ip_fragment = -1;
114 static const fragment_items ip_frag_items = {
119 &hf_ip_fragment_overlap,
120 &hf_ip_fragment_overlap_conflict,
121 &hf_ip_fragment_multiple_tails,
122 &hf_ip_fragment_too_long_fragment,
123 &hf_ip_fragment_error,
124 &hf_ip_reassembled_in,
128 static dissector_table_t ip_dissector_table;
130 static dissector_handle_t ip_handle;
131 static dissector_handle_t data_handle;
133 static int proto_icmp = -1;
134 static int hf_icmp_type = -1;
135 static int hf_icmp_code = -1;
136 static int hf_icmp_checksum = -1;
137 static int hf_icmp_checksum_bad = -1;
140 static int hf_icmp_mip_type = -1;
141 static int hf_icmp_mip_length = -1;
142 static int hf_icmp_mip_prefix_length = -1;
143 static int hf_icmp_mip_seq = -1;
144 static int hf_icmp_mip_life = -1;
145 static int hf_icmp_mip_flags = -1;
146 static int hf_icmp_mip_r = -1;
147 static int hf_icmp_mip_b = -1;
148 static int hf_icmp_mip_h = -1;
149 static int hf_icmp_mip_f = -1;
150 static int hf_icmp_mip_m = -1;
151 static int hf_icmp_mip_g = -1;
152 static int hf_icmp_mip_v = -1;
153 static int hf_icmp_mip_res = -1;
154 static int hf_icmp_mip_reserved = -1;
155 static int hf_icmp_mip_coa = -1;
156 static int hf_icmp_mip_challenge = -1;
158 static gint ett_icmp = -1;
159 static gint ett_icmp_mip = -1;
160 static gint ett_icmp_mip_flags = -1;
162 /* ICMP definitions */
164 #define ICMP_ECHOREPLY 0
165 #define ICMP_UNREACH 3
166 #define ICMP_SOURCEQUENCH 4
167 #define ICMP_REDIRECT 5
169 #define ICMP_RTRADVERT 9
170 #define ICMP_RTRSOLICIT 10
171 #define ICMP_TIMXCEED 11
172 #define ICMP_PARAMPROB 12
173 #define ICMP_TSTAMP 13
174 #define ICMP_TSTAMPREPLY 14
176 #define ICMP_IREQREPLY 16
177 #define ICMP_MASKREQ 17
178 #define ICMP_MASKREPLY 18
180 /* ICMP UNREACHABLE */
182 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
183 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
184 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
185 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
186 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
187 #define ICMP_SR_FAILED 5 /* Source Route failed */
188 #define ICMP_NET_UNKNOWN 6
189 #define ICMP_HOST_UNKNOWN 7
190 #define ICMP_HOST_ISOLATED 8
191 #define ICMP_NET_ANO 9
192 #define ICMP_HOST_ANO 10
193 #define ICMP_NET_UNR_TOS 11
194 #define ICMP_HOST_UNR_TOS 12
195 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
196 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
197 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
200 /* IP structs and definitions */
202 /* Offsets of fields within an IP header. */
214 /* Minimum IP header length. */
215 #define IPH_MIN_LEN 20
218 #define IP_CE 0x8000 /* Flag: "Congestion" */
219 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
220 #define IP_MF 0x2000 /* Flag: "More Fragments" */
221 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
223 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
224 #define IPDSFIELD_DSCP_MASK 0xFC
225 #define IPDSFIELD_ECN_MASK 0x03
226 #define IPDSFIELD_DSCP_SHIFT 2
227 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
228 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
229 #define IPDSFIELD_DSCP_DEFAULT 0x00
230 #define IPDSFIELD_DSCP_CS1 0x08
231 #define IPDSFIELD_DSCP_CS2 0x10
232 #define IPDSFIELD_DSCP_CS3 0x18
233 #define IPDSFIELD_DSCP_CS4 0x20
234 #define IPDSFIELD_DSCP_CS5 0x28
235 #define IPDSFIELD_DSCP_CS6 0x30
236 #define IPDSFIELD_DSCP_CS7 0x38
237 #define IPDSFIELD_DSCP_AF11 0x0A
238 #define IPDSFIELD_DSCP_AF12 0x0C
239 #define IPDSFIELD_DSCP_AF13 0x0E
240 #define IPDSFIELD_DSCP_AF21 0x12
241 #define IPDSFIELD_DSCP_AF22 0x14
242 #define IPDSFIELD_DSCP_AF23 0x16
243 #define IPDSFIELD_DSCP_AF31 0x1A
244 #define IPDSFIELD_DSCP_AF32 0x1C
245 #define IPDSFIELD_DSCP_AF33 0x1E
246 #define IPDSFIELD_DSCP_AF41 0x22
247 #define IPDSFIELD_DSCP_AF42 0x24
248 #define IPDSFIELD_DSCP_AF43 0x26
249 #define IPDSFIELD_DSCP_EF 0x2E
250 #define IPDSFIELD_ECT_MASK 0x02
251 #define IPDSFIELD_CE_MASK 0x01
253 /* IP TOS, superseded by the DS Field, RFC 2474. */
254 #define IPTOS_TOS_MASK 0x1E
255 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
256 #define IPTOS_NONE 0x00
257 #define IPTOS_LOWCOST 0x02
258 #define IPTOS_RELIABILITY 0x04
259 #define IPTOS_THROUGHPUT 0x08
260 #define IPTOS_LOWDELAY 0x10
261 #define IPTOS_SECURITY 0x1E
263 #define IPTOS_PREC_MASK 0xE0
264 #define IPTOS_PREC_SHIFT 5
265 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
266 #define IPTOS_PREC_NETCONTROL 7
267 #define IPTOS_PREC_INTERNETCONTROL 6
268 #define IPTOS_PREC_CRITIC_ECP 5
269 #define IPTOS_PREC_FLASHOVERRIDE 4
270 #define IPTOS_PREC_FLASH 3
271 #define IPTOS_PREC_IMMEDIATE 2
272 #define IPTOS_PREC_PRIORITY 1
273 #define IPTOS_PREC_ROUTINE 0
276 #define IPOPT_COPY 0x80
278 #define IPOPT_CONTROL 0x00
279 #define IPOPT_RESERVED1 0x20
280 #define IPOPT_MEASUREMENT 0x40
281 #define IPOPT_RESERVED2 0x60
283 #define IPOPT_END (0 |IPOPT_CONTROL)
284 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
285 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
286 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
287 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
288 #define IPOPT_RR (7 |IPOPT_CONTROL)
289 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
290 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
291 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
293 /* IP option lengths */
294 #define IPOLEN_SEC 11
295 #define IPOLEN_LSRR_MIN 3
296 #define IPOLEN_TIMESTAMP_MIN 5
297 #define IPOLEN_RR_MIN 3
299 #define IPOLEN_SSRR_MIN 3
302 #define IPSEC_UNCLASSIFIED 0x0000
303 #define IPSEC_CONFIDENTIAL 0xF135
304 #define IPSEC_EFTO 0x789A
305 #define IPSEC_MMMM 0xBC4D
306 #define IPSEC_RESTRICTED 0xAF13
307 #define IPSEC_SECRET 0xD788
308 #define IPSEC_TOPSECRET 0x6BC5
309 #define IPSEC_RESERVED1 0x35E2
310 #define IPSEC_RESERVED2 0x9AF1
311 #define IPSEC_RESERVED3 0x4D78
312 #define IPSEC_RESERVED4 0x24BD
313 #define IPSEC_RESERVED5 0x135E
314 #define IPSEC_RESERVED6 0x89AF
315 #define IPSEC_RESERVED7 0xC4D6
316 #define IPSEC_RESERVED8 0xE26B
318 #define IPOPT_TS_TSONLY 0 /* timestamps only */
319 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
320 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
323 * defragmentation of IPv4
325 static GHashTable *ip_fragment_table = NULL;
326 static GHashTable *ip_reassembled_table = NULL;
329 ip_defragment_init(void)
331 fragment_table_init(&ip_fragment_table);
332 reassembled_table_init(&ip_reassembled_table);
336 capture_ip(const guchar *pd, int offset, int len, packet_counts *ld) {
337 if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
341 switch (pd[offset + 9]) {
352 case IP_PROTO_ICMPV6: /* XXX - separate counters? */
370 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
371 guint optlen, packet_info *pinfo _U_,
372 proto_tree *opt_tree)
374 proto_tree *field_tree = NULL;
377 static const value_string secl_vals[] = {
378 {IPSEC_UNCLASSIFIED, "Unclassified"},
379 {IPSEC_CONFIDENTIAL, "Confidential"},
380 {IPSEC_EFTO, "EFTO" },
381 {IPSEC_MMMM, "MMMM" },
382 {IPSEC_RESTRICTED, "Restricted" },
383 {IPSEC_SECRET, "Secret" },
384 {IPSEC_TOPSECRET, "Top secret" },
385 {IPSEC_RESERVED1, "Reserved" },
386 {IPSEC_RESERVED2, "Reserved" },
387 {IPSEC_RESERVED3, "Reserved" },
388 {IPSEC_RESERVED4, "Reserved" },
389 {IPSEC_RESERVED5, "Reserved" },
390 {IPSEC_RESERVED6, "Reserved" },
391 {IPSEC_RESERVED7, "Reserved" },
392 {IPSEC_RESERVED8, "Reserved" },
395 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
396 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
399 val = tvb_get_ntohs(tvb, offset);
400 proto_tree_add_text(field_tree, tvb, offset, 2,
401 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
404 val = tvb_get_ntohs(tvb, offset);
405 proto_tree_add_text(field_tree, tvb, offset, 2,
406 "Compartments: %u", val);
409 proto_tree_add_text(field_tree, tvb, offset, 2,
410 "Handling restrictions: %c%c",
411 tvb_get_guint8(tvb, offset),
412 tvb_get_guint8(tvb, offset + 1));
415 proto_tree_add_text(field_tree, tvb, offset, 3,
416 "Transmission control code: %c%c%c",
417 tvb_get_guint8(tvb, offset),
418 tvb_get_guint8(tvb, offset + 1),
419 tvb_get_guint8(tvb, offset + 2));
423 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
424 guint optlen, packet_info *pinfo _U_,
425 proto_tree *opt_tree)
427 proto_tree *field_tree = NULL;
433 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
435 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
437 optoffset += 2; /* skip past type and length */
438 optlen -= 2; /* subtract size of type and length */
440 ptr = tvb_get_guint8(tvb, offset + optoffset);
441 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
442 "Pointer: %d%s", ptr,
443 ((ptr < 4) ? " (points before first address)" :
444 ((ptr & 3) ? " (points to middle of address)" : "")));
447 ptr--; /* ptr is 1-origin */
451 proto_tree_add_text(field_tree, tvb, offset, optlen,
452 "(suboption would go past end of option)");
456 /* Avoids alignment problems on many architectures. */
457 tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
459 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
461 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
462 ((optoffset == ptr) ? " <- (current)" : ""));
469 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
470 guint optlen, packet_info *pinfo _U_,
471 proto_tree *opt_tree)
473 proto_tree_add_text(opt_tree, tvb, offset, optlen,
474 "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
479 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
480 int offset, guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
482 proto_tree *field_tree = NULL;
487 static const value_string flag_vals[] = {
488 {IPOPT_TS_TSONLY, "Time stamps only" },
489 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
490 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
495 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
496 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
498 optoffset += 2; /* skip past type and length */
499 optlen -= 2; /* subtract size of type and length */
501 ptr = tvb_get_guint8(tvb, offset + optoffset);
502 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
503 "Pointer: %d%s", ptr,
504 ((ptr < 5) ? " (points before first address)" :
505 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
508 ptr--; /* ptr is 1-origin */
510 flg = tvb_get_guint8(tvb, offset + optoffset);
511 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
512 "Overflow: %u", flg >> 4);
514 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
515 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
520 if (flg == IPOPT_TS_TSANDADDR) {
522 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
523 "(suboption would go past end of option)");
526 tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
527 ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
529 proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
530 "Address = %s, time stamp = %u",
531 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
536 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
537 "(suboption would go past end of option)");
540 ts = tvb_get_ntohl(tvb, offset + optoffset);
542 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
543 "Time stamp = %u", ts);
550 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
551 guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
553 /* Router-Alert, as defined by RFC2113 */
554 int opt = tvb_get_ntohs(tvb, offset + 2);
555 static const value_string ra_opts[] = {
556 {0, "Every router examines packet"},
560 proto_tree_add_text(opt_tree, tvb, offset, optlen,
561 "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
565 static const ip_tcp_opt ipopts[] = {
588 dissect_ipopt_security
592 "Strict source route",
593 &ett_ip_option_route,
600 "Loose source route",
601 &ett_ip_option_route,
609 &ett_ip_option_route,
625 &ett_ip_option_timestamp,
627 IPOLEN_TIMESTAMP_MIN,
628 dissect_ipopt_timestamp
640 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
642 /* Dissect the IP or TCP options in a packet. */
644 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
645 const ip_tcp_opt *opttab, int nopts, int eol,
646 packet_info *pinfo, proto_tree *opt_tree)
649 const ip_tcp_opt *optp;
650 opt_len_type len_type;
653 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
654 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
655 int, guint, packet_info *, proto_tree *);
659 opt = tvb_get_guint8(tvb, offset);
660 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
661 if (optp->optcode == opt)
664 if (optp == &opttab[nopts]) {
665 /* We assume that the only NO_LENGTH options are EOL and NOP options,
666 so that we can treat unknown options as VARIABLE_LENGTH with a
667 minimum of 2, and at least be able to move on to the next option
668 by using the length in the option. */
669 optp = NULL; /* indicate that we don't know this option */
670 len_type = VARIABLE_LENGTH;
672 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
676 len_type = optp->len_type;
677 optlen = optp->optlen;
679 dissect = optp->dissect;
681 --length; /* account for type byte */
682 if (len_type != NO_LENGTH) {
683 /* Option has a length. Is it in the packet? */
685 /* Bogus - packet must at least include option code byte and
687 proto_tree_add_text(opt_tree, tvb, offset, 1,
688 "%s (length byte past end of options)", name);
691 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
692 --length; /* account for length byte */
694 /* Bogus - option length is too short to include option code and
696 proto_tree_add_text(opt_tree, tvb, offset, 2,
697 "%s (with too-short option length = %u byte%s)", name,
698 len, plurality(len, "", "s"));
700 } else if (len - 2 > length) {
701 /* Bogus - option goes past the end of the header. */
702 proto_tree_add_text(opt_tree, tvb, offset, length,
703 "%s (option length = %u byte%s says option goes past end of options)",
704 name, len, plurality(len, "", "s"));
706 } else if (len_type == FIXED_LENGTH && len != optlen) {
707 /* Bogus - option length isn't what it's supposed to be for this
709 proto_tree_add_text(opt_tree, tvb, offset, len,
710 "%s (with option length = %u byte%s; should be %u)", name,
711 len, plurality(len, "", "s"), optlen);
713 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
714 /* Bogus - option length is less than what it's supposed to be for
716 proto_tree_add_text(opt_tree, tvb, offset, len,
717 "%s (with option length = %u byte%s; should be >= %u)", name,
718 len, plurality(len, "", "s"), optlen);
722 proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
723 name, len, plurality(len, "", "s"));
725 if (dissect != NULL) {
726 /* Option has a dissector. */
727 (*dissect)(optp, tvb, offset, len, pinfo, opt_tree);
729 /* Option has no data, hence no dissector. */
730 proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
733 len -= 2; /* subtract size of type and length */
738 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
746 const value_string dscp_vals[] = {
747 { IPDSFIELD_DSCP_DEFAULT, "Default" },
748 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
749 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
750 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
751 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
752 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
753 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
754 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
755 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
756 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
757 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
758 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
759 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
760 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
761 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
762 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
763 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
764 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
765 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
766 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
767 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
770 static const value_string precedence_vals[] = {
771 { IPTOS_PREC_ROUTINE, "routine" },
772 { IPTOS_PREC_PRIORITY, "priority" },
773 { IPTOS_PREC_IMMEDIATE, "immediate" },
774 { IPTOS_PREC_FLASH, "flash" },
775 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
776 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
777 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
778 { IPTOS_PREC_NETCONTROL, "network control" },
781 static const value_string iptos_vals[] = {
782 { IPTOS_NONE, "None" },
783 { IPTOS_LOWCOST, "Minimize cost" },
784 { IPTOS_RELIABILITY, "Maximize reliability" },
785 { IPTOS_THROUGHPUT, "Maximize throughput" },
786 { IPTOS_LOWDELAY, "Minimize delay" },
787 { IPTOS_SECURITY, "Maximize security" },
791 static const true_false_string tos_set_low = {
796 static const true_false_string tos_set_high = {
801 static guint16 ip_checksum(const guint8 *ptr, int len)
805 cksum_vec[0].ptr = ptr;
806 cksum_vec[0].len = len;
807 return in_cksum(&cksum_vec[0], 1);
811 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
813 proto_tree *ip_tree = NULL, *field_tree;
814 proto_item *ti = NULL, *tf;
821 fragment_data *ipfd_head=NULL;
823 gboolean update_col_info = TRUE;
824 gboolean save_fragmented;
825 static e_ip eip_arr[4];
826 static int eip_current=0;
833 iph=&eip_arr[eip_current];
835 if (check_col(pinfo->cinfo, COL_PROTOCOL))
836 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
837 if (check_col(pinfo->cinfo, COL_INFO))
838 col_clear(pinfo->cinfo, COL_INFO);
840 iph->ip_v_hl = tvb_get_guint8(tvb, offset);
841 hlen = lo_nibble(iph->ip_v_hl) * 4; /* IP header length, in bytes */
844 ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
845 ip_tree = proto_item_add_subtree(ti, ett_ip);
847 proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1,
848 hi_nibble(iph->ip_v_hl));
851 if (hlen < IPH_MIN_LEN) {
852 if (check_col(pinfo->cinfo, COL_INFO))
853 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
856 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
857 "Header length: %u bytes (bogus, must be at least %u)", hlen,
864 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
865 "Header length: %u bytes", hlen);
868 iph->ip_tos = tvb_get_guint8(tvb, offset + 1);
870 if (g_ip_dscp_actif) {
871 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph->ip_tos,
872 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph->ip_tos,
873 IPDSFIELD_DSCP(iph->ip_tos), val_to_str(IPDSFIELD_DSCP(iph->ip_tos), dscp_vals,
874 "Unknown DSCP"),IPDSFIELD_ECN(iph->ip_tos));
876 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
877 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph->ip_tos);
878 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph->ip_tos);
879 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph->ip_tos);
881 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph->ip_tos,
882 "Type of service: 0x%02x (%s)", iph->ip_tos,
883 val_to_str( IPTOS_TOS(iph->ip_tos), iptos_vals, "Unknown") );
885 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
886 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph->ip_tos);
887 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph->ip_tos);
888 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph->ip_tos);
889 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph->ip_tos);
890 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph->ip_tos);
894 /* Length of IP datagram.
895 XXX - what if this is greater than the reported length of the
896 tvbuff? This could happen, for example, in an IP datagram
897 inside an ICMP datagram; we need to somehow let the
898 dissector we call know that, as it might want to avoid
899 doing its checksumming. */
900 iph->ip_len = tvb_get_ntohs(tvb, offset + 2);
902 /* Adjust the length of this tvbuff to include only the IP datagram. */
903 set_actual_length(tvb, iph->ip_len);
905 if (iph->ip_len < hlen) {
906 if (check_col(pinfo->cinfo, COL_INFO))
907 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP length (%u, less than header length %u)",
910 proto_tree_add_uint_format(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len,
911 "Total length: %u bytes (bogus, less than header length %u)", iph->ip_len,
917 proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len);
919 iph->ip_id = tvb_get_ntohs(tvb, offset + 4);
921 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);
923 iph->ip_off = tvb_get_ntohs(tvb, offset + 6);
925 flags = (iph->ip_off & (IP_DF|IP_MF)) >> 12;
926 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
927 field_tree = proto_item_add_subtree(tf, ett_ip_off);
928 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
929 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
931 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
932 (iph->ip_off & IP_OFFSET)*8);
936 proto_tree_add_item(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, FALSE);
938 iph->ip_p = tvb_get_guint8(tvb, offset + 9);
940 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph->ip_p,
941 "Protocol: %s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
944 iph->ip_sum = tvb_get_ntohs(tvb, offset + 10);
947 * If we have the entire IP header available, check the checksum.
949 if (tvb_bytes_exist(tvb, offset, hlen)) {
950 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
953 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
954 "Header checksum: 0x%04x (correct)", iph->ip_sum);
957 proto_tree_add_boolean_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
958 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
959 "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph->ip_sum,
960 in_cksum_shouldbe(iph->ip_sum, ipsum));
966 proto_tree_add_uint(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum);
969 SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
970 SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
971 SET_ADDRESS(&iph->ip_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
973 memcpy(&addr, iph->ip_src.data, 4);
974 if (ip_summary_in_tree) {
975 proto_item_append_text(ti, ", Src Addr: %s (%s)",
976 get_hostname(addr), ip_to_str((guint8 *) iph->ip_src.data));
978 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, addr);
979 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, addr);
982 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
983 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
984 SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
987 memcpy(&addr, iph->ip_dst.data, 4);
988 if (ip_summary_in_tree) {
989 proto_item_append_text(ti, ", Dst Addr: %s (%s)",
990 get_hostname(addr), ip_to_str((guint8 *) iph->ip_dst.data));
992 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, addr);
993 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, addr);
997 /* Decode IP options, if any. */
998 if (hlen > IPH_MIN_LEN) {
999 /* There's more than just the fixed-length header. Decode the
1001 optlen = hlen - IPH_MIN_LEN; /* length of options, in bytes */
1002 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
1003 "Options: (%u bytes)", optlen);
1004 field_tree = proto_item_add_subtree(tf, ett_ip_options);
1005 dissect_ip_tcp_options(tvb, offset + 20, optlen,
1006 ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
1010 pinfo->ipproto = iph->ip_p;
1012 pinfo->iplen = iph->ip_len;
1014 pinfo->iphdrlen = hlen;
1016 /* Skip over header + options */
1018 nxt = iph->ip_p; /* XXX - what if this isn't the same for all fragments? */
1020 /* If ip_defragment is on, this is a fragment, we have all the data
1021 * in the fragment, and the header checksum is valid, then just add
1022 * the fragment to the hashtable.
1024 save_fragmented = pinfo->fragmented;
1025 if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
1026 tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
1028 ipfd_head = fragment_add_check(tvb, offset, pinfo, iph->ip_id,
1030 ip_reassembled_table,
1031 (iph->ip_off & IP_OFFSET)*8,
1032 pinfo->iplen - pinfo->iphdrlen,
1033 iph->ip_off & IP_MF);
1035 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv4",
1036 ipfd_head, &ip_frag_items, &update_col_info, ip_tree);
1038 /* If this is the first fragment, dissect its contents, otherwise
1039 just show it as a fragment.
1041 XXX - if we eventually don't save the reassembled contents of all
1042 fragmented datagrams, we may want to always reassemble. */
1043 if (iph->ip_off & IP_OFFSET) {
1044 /* Not the first fragment - don't dissect it. */
1047 /* First fragment, or not fragmented. Dissect what we have here. */
1049 /* Get a tvbuff for the payload. */
1050 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1053 * If this is the first fragment, but not the only fragment,
1054 * tell the next protocol that.
1056 if (iph->ip_off & IP_MF)
1057 pinfo->fragmented = TRUE;
1059 pinfo->fragmented = FALSE;
1063 if (next_tvb == NULL) {
1064 /* Just show this as a fragment. */
1065 if (check_col(pinfo->cinfo, COL_INFO)) {
1066 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1067 ipprotostr(iph->ip_p), iph->ip_p, (iph->ip_off & IP_OFFSET) * 8);
1069 if( ipfd_head && ipfd_head->reassembled_in != pinfo->fd->num ){
1070 if (check_col(pinfo->cinfo, COL_INFO)) {
1071 col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]",
1072 ipfd_head->reassembled_in);
1076 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
1078 pinfo->fragmented = save_fragmented;
1082 /* Hand off to the next protocol.
1084 XXX - setting the columns only after trying various dissectors means
1085 that if one of those dissectors throws an exception, the frame won't
1086 even be labelled as an IP frame; ideally, if a frame being dissected
1087 throws an exception, it'll be labelled as a mangled frame of the
1088 type in question. */
1089 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
1090 /* Unknown protocol */
1091 if (update_col_info) {
1092 if (check_col(pinfo->cinfo, COL_INFO))
1093 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
1095 call_dissector(data_handle,next_tvb, pinfo, tree);
1097 pinfo->fragmented = save_fragmented;
1100 tap_queue_packet(ip_tap, pinfo, iph);
1104 #define ICMP_MIP_EXTENSION_PAD 0
1105 #define ICMP_MIP_MOB_AGENT_ADV 16
1106 #define ICMP_MIP_PREFIX_LENGTHS 19
1107 #define ICMP_MIP_CHALLENGE 24
1109 static value_string mip_extensions[] = {
1110 { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
1111 { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1113 { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
1114 { ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
1119 * Dissect the mobile ip advertisement extensions.
1122 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1128 proto_tree *mip_tree=NULL;
1129 proto_tree *flags_tree=NULL;
1133 /* Not much to do if we're not parsing everything */
1136 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1138 type = tvb_get_guint8(tvb, offset + 0);
1140 length = tvb_get_guint8(tvb, offset + 1);
1144 ti = proto_tree_add_text(tree, tvb, offset,
1145 type?(length + 2):1,
1147 val_to_str(type, mip_extensions,
1149 mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1153 case ICMP_MIP_EXTENSION_PAD:
1154 /* One byte padding extension */
1155 /* Add our fields */
1157 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1161 case ICMP_MIP_MOB_AGENT_ADV:
1162 /* Mobility Agent Advertisement Extension (RFC 2002)*/
1163 /* Add our fields */
1165 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1169 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1172 /* sequence number */
1173 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset,
1176 /* Registration Lifetime */
1177 proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset,
1181 flags = tvb_get_guint8(tvb, offset);
1182 ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1184 flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1185 proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1186 proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1187 proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1188 proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1189 proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1190 proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1191 proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1192 proto_tree_add_boolean(flags_tree, hf_icmp_mip_res, tvb, offset, 1, flags);
1196 proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset,
1201 numCOAs = (length - 6) / 4;
1202 for (i=0; i<numCOAs; i++) {
1203 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset,
1208 case ICMP_MIP_PREFIX_LENGTHS:
1209 /* Prefix-Lengths Extension (RFC 2002)*/
1210 /* Add our fields */
1212 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1216 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1220 /* prefix lengths */
1221 for(i=0; i<length; i++) {
1222 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1227 case ICMP_MIP_CHALLENGE:
1228 /* Challenge Extension (RFC 3012)*/
1230 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1234 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1238 proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset,
1244 g_warning("Unknown type(%u)! I hope the length is right (%u)",
1246 offset += length + 2;
1251 } /* dissect_mip_extensions */
1253 static const gchar *unreach_str[] = {"Network unreachable",
1255 "Protocol unreachable",
1257 "Fragmentation needed",
1258 "Source route failed",
1259 "Destination network unknown",
1260 "Destination host unknown",
1261 "Source host isolated",
1262 "Network administratively prohibited",
1263 "Host administratively prohibited",
1264 "Network unreachable for TOS",
1265 "Host unreachable for TOS",
1266 "Communication administratively filtered",
1267 "Host precedence violation",
1268 "Precedence cutoff in effect"};
1270 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1272 static const gchar *redir_str[] = {"Redirect for network",
1273 "Redirect for host",
1274 "Redirect for TOS and network",
1275 "Redirect for TOS and host"};
1277 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1279 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
1280 "TTL equals 0 during reassembly"};
1282 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1284 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1286 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1289 * RFC 792 for basic ICMP.
1290 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1291 * RFC 1256 for router discovery messages.
1292 * RFC 2002 and 3012 for Mobile IP stuff.
1295 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1297 proto_tree *icmp_tree;
1301 guint length, reported_length;
1302 guint16 cksum, computed_cksum;
1303 gchar type_str[64], code_str[64] = "";
1304 guint8 num_addrs = 0;
1305 guint8 addr_entry_size = 0;
1307 gboolean save_in_error_pkt;
1310 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1311 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1312 if (check_col(pinfo->cinfo, COL_INFO))
1313 col_clear(pinfo->cinfo, COL_INFO);
1315 /* To do: check for runts, errs, etc. */
1316 icmp_type = tvb_get_guint8(tvb, 0);
1317 icmp_code = tvb_get_guint8(tvb, 1);
1318 cksum = tvb_get_ntohs(tvb, 2);
1320 switch (icmp_type) {
1321 case ICMP_ECHOREPLY:
1322 strcpy(type_str, "Echo (ping) reply");
1325 strcpy(type_str, "Destination unreachable");
1326 if (icmp_code < N_UNREACH) {
1327 sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1329 strcpy(code_str, "(Unknown - error?)");
1332 case ICMP_SOURCEQUENCH:
1333 strcpy(type_str, "Source quench (flow control)");
1336 strcpy(type_str, "Redirect");
1337 if (icmp_code < N_REDIRECT) {
1338 sprintf(code_str, "(%s)", redir_str[icmp_code]);
1340 strcpy(code_str, "(Unknown - error?)");
1344 strcpy(type_str, "Echo (ping) request");
1346 case ICMP_RTRADVERT:
1347 switch (icmp_code) {
1348 case 16: /* Mobile-Ip */
1349 strcpy(type_str, "Mobile IP Advertisement");
1352 strcpy(type_str, "Router advertisement");
1354 } /* switch icmp_code */
1356 case ICMP_RTRSOLICIT:
1357 strcpy(type_str, "Router solicitation");
1360 strcpy(type_str, "Time-to-live exceeded");
1361 if (icmp_code < N_TIMXCEED) {
1362 sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1364 strcpy(code_str, "(Unknown - error?)");
1367 case ICMP_PARAMPROB:
1368 strcpy(type_str, "Parameter problem");
1369 if (icmp_code < N_PARAMPROB) {
1370 sprintf(code_str, "(%s)", par_str[icmp_code]);
1372 strcpy(code_str, "(Unknown - error?)");
1376 strcpy(type_str, "Timestamp request");
1378 case ICMP_TSTAMPREPLY:
1379 strcpy(type_str, "Timestamp reply");
1382 strcpy(type_str, "Information request");
1384 case ICMP_IREQREPLY:
1385 strcpy(type_str, "Information reply");
1388 strcpy(type_str, "Address mask request");
1390 case ICMP_MASKREPLY:
1391 strcpy(type_str, "Address mask reply");
1394 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1398 if (check_col(pinfo->cinfo, COL_INFO))
1399 col_add_str(pinfo->cinfo, COL_INFO, type_str);
1402 length = tvb_length(tvb);
1403 reported_length = tvb_reported_length(tvb);
1404 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1405 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1406 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1409 icmp_type, type_str);
1410 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1413 icmp_code, code_str);
1415 if (!pinfo->fragmented && length >= reported_length) {
1416 /* The packet isn't part of a fragmented datagram and isn't
1417 truncated, so we can checksum it. */
1419 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1421 if (computed_cksum == 0) {
1422 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1424 "Checksum: 0x%04x (correct)", cksum);
1426 proto_tree_add_boolean_hidden(icmp_tree, hf_icmp_checksum_bad,
1428 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1430 "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1431 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1434 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1437 /* Decode the second 4 bytes of the packet. */
1438 switch (icmp_type) {
1439 case ICMP_ECHOREPLY:
1442 case ICMP_TSTAMPREPLY:
1444 case ICMP_IREQREPLY:
1446 case ICMP_MASKREPLY:
1447 proto_tree_add_text(icmp_tree, tvb, 4, 2, "Identifier: 0x%04x",
1448 tvb_get_ntohs(tvb, 4));
1449 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Sequence number: %02x:%02x",
1450 tvb_get_guint8(tvb, 6), tvb_get_guint8(tvb, 7));
1454 switch (icmp_code) {
1455 case ICMP_FRAG_NEEDED:
1456 proto_tree_add_text(icmp_tree, tvb, 6, 2, "MTU of next hop: %u",
1457 tvb_get_ntohs(tvb, 6));
1462 case ICMP_RTRADVERT:
1463 num_addrs = tvb_get_guint8(tvb, 4);
1464 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1466 addr_entry_size = tvb_get_guint8(tvb, 5);
1467 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1469 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1470 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1473 case ICMP_PARAMPROB:
1474 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1475 tvb_get_guint8(tvb, 4));
1479 proto_tree_add_text(icmp_tree, tvb, 4, 4, "Gateway address: %s",
1480 ip_to_str(tvb_get_ptr(tvb, 4, 4)));
1484 /* Decode the additional information in the packet. */
1485 switch (icmp_type) {
1488 case ICMP_PARAMPROB:
1489 case ICMP_SOURCEQUENCH:
1491 /* Save the current value of the "we're inside an error packet"
1492 flag, and set that flag; subdissectors may treat packets
1493 that are the payload of error packets differently from
1495 save_in_error_pkt = pinfo->in_error_pkt;
1496 pinfo->in_error_pkt = TRUE;
1498 /* Decode the IP header and first 64 bits of data from the
1499 original datagram. */
1500 next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1501 call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1503 /* Restore the "we're inside an error packet" flag. */
1504 pinfo->in_error_pkt = save_in_error_pkt;
1507 case ICMP_ECHOREPLY:
1509 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1513 case ICMP_RTRADVERT:
1514 if (addr_entry_size == 2) {
1515 for (i = 0; i < num_addrs; i++) {
1516 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1517 "Router address: %s",
1518 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1519 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1520 "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1522 if (icmp_code == 16) {
1524 dissect_mip_extensions(tvb, 8 + i*8, icmp_tree);
1527 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1532 case ICMP_TSTAMPREPLY:
1533 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1534 tvb_get_ntohl(tvb, 8));
1535 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1536 tvb_get_ntohl(tvb, 12));
1537 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1538 tvb_get_ntohl(tvb, 16));
1542 case ICMP_MASKREPLY:
1543 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1544 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1551 proto_register_ip(void)
1553 static hf_register_info hf[] = {
1556 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1560 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1564 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1567 { &hf_ip_dsfield_dscp,
1568 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1569 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1572 { &hf_ip_dsfield_ect,
1573 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1577 { &hf_ip_dsfield_ce,
1578 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1583 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1586 { &hf_ip_tos_precedence,
1587 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1592 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1596 { &hf_ip_tos_throughput,
1597 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1601 { &hf_ip_tos_reliability,
1602 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1607 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1612 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1616 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1620 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1624 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1628 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1632 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1636 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1640 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1643 { &hf_ip_frag_offset,
1644 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1648 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1652 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1656 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1659 { &hf_ip_checksum_bad,
1660 { "Bad Header checksum", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1663 { &hf_ip_fragment_overlap,
1664 { "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1665 "Fragment overlaps with other fragments", HFILL }},
1667 { &hf_ip_fragment_overlap_conflict,
1668 { "Conflicting data in fragment overlap", "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1669 "Overlapping fragments contained conflicting data", HFILL }},
1671 { &hf_ip_fragment_multiple_tails,
1672 { "Multiple tail fragments found", "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1673 "Several tails were found when defragmenting the packet", HFILL }},
1675 { &hf_ip_fragment_too_long_fragment,
1676 { "Fragment too long", "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1677 "Fragment contained data past end of packet", HFILL }},
1679 { &hf_ip_fragment_error,
1680 { "Defragmentation error", "ip.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1681 "Defragmentation error due to illegal fragments", HFILL }},
1684 { "IP Fragment", "ip.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1685 "IP Fragment", HFILL }},
1688 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1689 "IP Fragments", HFILL }},
1691 { &hf_ip_reassembled_in,
1692 { "Reassembled IP in frame", "ip.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1693 "This IP packet is reassembled in this frame", HFILL }}
1695 static gint *ett[] = {
1702 &ett_ip_option_route,
1703 &ett_ip_option_timestamp,
1707 module_t *ip_module;
1709 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1710 proto_register_field_array(proto_ip, hf, array_length(hf));
1711 proto_register_subtree_array(ett, array_length(ett));
1713 /* subdissector code */
1714 ip_dissector_table = register_dissector_table("ip.proto",
1715 "IP protocol", FT_UINT8, BASE_DEC);
1717 /* Register configuration options */
1718 ip_module = prefs_register_protocol(proto_ip, NULL);
1719 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1720 "Decode IPv4 TOS field as DiffServ field",
1721 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1723 prefs_register_bool_preference(ip_module, "defragment",
1724 "Reassemble fragmented IP datagrams",
1725 "Whether fragmented IP datagrams should be reassembled",
1727 prefs_register_bool_preference(ip_module, "summary_in_tree",
1728 "Show IP summary in protocol tree",
1729 "Whether the IP summary line should be shown in the protocol tree",
1730 &ip_summary_in_tree);
1732 register_dissector("ip", dissect_ip, proto_ip);
1733 register_init_routine(ip_defragment_init);
1734 ip_tap=register_tap("ip");
1738 proto_reg_handoff_ip(void)
1740 dissector_handle_t ip_handle;
1742 data_handle = find_dissector("data");
1743 ip_handle = find_dissector("ip");
1744 dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
1745 dissector_add("ppp.protocol", PPP_IP, ip_handle);
1746 dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
1747 dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
1748 dissector_add("gre.proto", GRE_WCCP, ip_handle);
1749 dissector_add("llc.dsap", SAP_IP, ip_handle);
1750 dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
1751 dissector_add("null.type", BSD_AF_INET, ip_handle);
1752 dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
1753 dissector_add("fr.ietf", NLPID_IP, ip_handle);
1754 dissector_add("x.25.spi", NLPID_IP, ip_handle);
1755 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1051, ip_handle);
1756 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1201, ip_handle);
1760 proto_register_icmp(void)
1762 static hf_register_info hf[] = {
1765 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1769 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1772 { &hf_icmp_checksum,
1773 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1776 { &hf_icmp_checksum_bad,
1777 { "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1780 { &hf_icmp_mip_type,
1781 { "Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
1782 VALS(mip_extensions), 0x0,"", HFILL}},
1784 { &hf_icmp_mip_length,
1785 { "Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL, 0x0,
1788 { &hf_icmp_mip_prefix_length,
1789 { "Prefix Length", "icmp.mip.prefixlength", FT_UINT8, BASE_DEC, NULL, 0x0,
1793 { "Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC, NULL, 0x0,
1796 { &hf_icmp_mip_life,
1797 { "Registration Lifetime", "icmp.mip.life", FT_UINT16, BASE_DEC, NULL, 0x0,
1800 { &hf_icmp_mip_flags,
1801 { "Flags", "icmp.mip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1805 { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
1806 "Registration with this FA is required", HFILL }},
1809 { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
1810 "This FA will not accept requests at this time", HFILL }},
1813 { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
1814 "Home Agent Services Offered", HFILL }},
1817 { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
1818 "Foreign Agent Services Offered", HFILL }},
1821 { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
1822 "Minimal encapsulation tunneled datagram support", HFILL }},
1825 { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
1826 "GRE encapsulated tunneled datagram support", HFILL }},
1829 { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
1830 "Van Jacobson Header Compression Support", HFILL }},
1833 { "Reserved", "icmp.mip.res", FT_BOOLEAN, 8, NULL, 1,
1834 "Reserved", HFILL }},
1836 { &hf_icmp_mip_reserved,
1837 { "Reserved", "icmp.mip.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
1841 { "Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE, NULL, 0x0,
1844 { &hf_icmp_mip_challenge,
1845 { "Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE, NULL, 0x0,
1848 static gint *ett[] = {
1854 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
1856 proto_register_field_array(proto_icmp, hf, array_length(hf));
1857 proto_register_subtree_array(ett, array_length(ett));
1861 proto_reg_handoff_icmp(void)
1863 dissector_handle_t icmp_handle;
1866 * Get handle for the IP dissector.
1868 ip_handle = find_dissector("ip");
1870 icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
1871 dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);