2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.138 2001/06/19 23:08:55 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
33 #ifdef HAVE_NETINET_IN_H
34 # include <netinet/in.h>
41 #ifdef NEED_SNPRINTF_H
42 # include "snprintf.h"
49 #include "reassemble.h"
55 #include "packet-ip.h"
56 #include "packet-ipsec.h"
60 static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
62 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
63 static gboolean g_ip_dscp_actif = TRUE;
65 /* Defragment fragmented IP datagrams */
66 static gboolean ip_defragment = FALSE;
68 /* Place IP summary in proto tree */
69 static gboolean ip_summary_in_tree = TRUE;
71 static int proto_ip = -1;
72 static int hf_ip_version = -1;
73 static int hf_ip_hdr_len = -1;
74 static int hf_ip_dsfield = -1;
75 static int hf_ip_dsfield_dscp = -1;
76 static int hf_ip_dsfield_ect = -1;
77 static int hf_ip_dsfield_ce = -1;
78 static int hf_ip_tos = -1;
79 static int hf_ip_tos_precedence = -1;
80 static int hf_ip_tos_delay = -1;
81 static int hf_ip_tos_throughput = -1;
82 static int hf_ip_tos_reliability = -1;
83 static int hf_ip_tos_cost = -1;
84 static int hf_ip_len = -1;
85 static int hf_ip_id = -1;
86 static int hf_ip_dst = -1;
87 static int hf_ip_src = -1;
88 static int hf_ip_addr = -1;
89 static int hf_ip_flags = -1;
90 static int hf_ip_flags_df = -1;
91 static int hf_ip_flags_mf = -1;
92 static int hf_ip_frag_offset = -1;
93 static int hf_ip_ttl = -1;
94 static int hf_ip_proto = -1;
95 static int hf_ip_checksum = -1;
96 static int hf_ip_checksum_bad = -1;
97 static int hf_ip_fragments = -1;
98 static int hf_ip_fragment = -1;
99 static int hf_ip_fragment_overlap = -1;
100 static int hf_ip_fragment_overlap_conflict = -1;
101 static int hf_ip_fragment_multiple_tails = -1;
102 static int hf_ip_fragment_too_long_fragment = -1;
103 static int hf_ip_fragment_error = -1;
105 static gint ett_ip = -1;
106 static gint ett_ip_dsfield = -1;
107 static gint ett_ip_tos = -1;
108 static gint ett_ip_off = -1;
109 static gint ett_ip_options = -1;
110 static gint ett_ip_option_sec = -1;
111 static gint ett_ip_option_route = -1;
112 static gint ett_ip_option_timestamp = -1;
113 static gint ett_ip_fragments = -1;
114 static gint ett_ip_fragment = -1;
116 /* Used by IPv6 as well, so not static */
117 dissector_table_t ip_dissector_table;
119 static int proto_icmp = -1;
120 static int hf_icmp_type = -1;
121 static int hf_icmp_code = -1;
122 static int hf_icmp_checksum = -1;
123 static int hf_icmp_checksum_bad = -1;
125 static gint ett_icmp = -1;
127 /* ICMP definitions */
129 #define ICMP_ECHOREPLY 0
130 #define ICMP_UNREACH 3
131 #define ICMP_SOURCEQUENCH 4
132 #define ICMP_REDIRECT 5
134 #define ICMP_RTRADVERT 9
135 #define ICMP_RTRSOLICIT 10
136 #define ICMP_TIMXCEED 11
137 #define ICMP_PARAMPROB 12
138 #define ICMP_TSTAMP 13
139 #define ICMP_TSTAMPREPLY 14
141 #define ICMP_IREQREPLY 16
142 #define ICMP_MASKREQ 17
143 #define ICMP_MASKREPLY 18
145 /* ICMP UNREACHABLE */
147 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
148 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
149 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
150 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
151 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
152 #define ICMP_SR_FAILED 5 /* Source Route failed */
153 #define ICMP_NET_UNKNOWN 6
154 #define ICMP_HOST_UNKNOWN 7
155 #define ICMP_HOST_ISOLATED 8
156 #define ICMP_NET_ANO 9
157 #define ICMP_HOST_ANO 10
158 #define ICMP_NET_UNR_TOS 11
159 #define ICMP_HOST_UNR_TOS 12
160 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
161 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
162 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
165 /* IP structs and definitions */
169 guint8 ip_v_hl; /* combines ip_v and ip_hl */
181 /* Offsets of fields within an IP header. */
193 /* Minimum IP header length. */
194 #define IPH_MIN_LEN 20
197 #define IP_CE 0x8000 /* Flag: "Congestion" */
198 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
199 #define IP_MF 0x2000 /* Flag: "More Fragments" */
200 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
202 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
203 #define IPDSFIELD_DSCP_MASK 0xFC
204 #define IPDSFIELD_ECN_MASK 0x03
205 #define IPDSFIELD_DSCP_SHIFT 2
206 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
207 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
208 #define IPDSFIELD_DSCP_DEFAULT 0x00
209 #define IPDSFIELD_DSCP_CS1 0x08
210 #define IPDSFIELD_DSCP_CS2 0x10
211 #define IPDSFIELD_DSCP_CS3 0x18
212 #define IPDSFIELD_DSCP_CS4 0x20
213 #define IPDSFIELD_DSCP_CS5 0x28
214 #define IPDSFIELD_DSCP_CS6 0x30
215 #define IPDSFIELD_DSCP_CS7 0x38
216 #define IPDSFIELD_DSCP_AF11 0x0A
217 #define IPDSFIELD_DSCP_AF12 0x0C
218 #define IPDSFIELD_DSCP_AF13 0x0E
219 #define IPDSFIELD_DSCP_AF21 0x12
220 #define IPDSFIELD_DSCP_AF22 0x14
221 #define IPDSFIELD_DSCP_AF23 0x16
222 #define IPDSFIELD_DSCP_AF31 0x1A
223 #define IPDSFIELD_DSCP_AF32 0x1C
224 #define IPDSFIELD_DSCP_AF33 0x1E
225 #define IPDSFIELD_DSCP_AF41 0x22
226 #define IPDSFIELD_DSCP_AF42 0x24
227 #define IPDSFIELD_DSCP_AF43 0x26
228 #define IPDSFIELD_DSCP_EF 0x2E
229 #define IPDSFIELD_ECT_MASK 0x02
230 #define IPDSFIELD_CE_MASK 0x01
232 /* IP TOS, superseded by the DS Field, RFC 2474. */
233 #define IPTOS_TOS_MASK 0x1E
234 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
235 #define IPTOS_NONE 0x00
236 #define IPTOS_LOWCOST 0x02
237 #define IPTOS_RELIABILITY 0x04
238 #define IPTOS_THROUGHPUT 0x08
239 #define IPTOS_LOWDELAY 0x10
240 #define IPTOS_SECURITY 0x1E
242 #define IPTOS_PREC_MASK 0xE0
243 #define IPTOS_PREC_SHIFT 5
244 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
245 #define IPTOS_PREC_NETCONTROL 7
246 #define IPTOS_PREC_INTERNETCONTROL 6
247 #define IPTOS_PREC_CRITIC_ECP 5
248 #define IPTOS_PREC_FLASHOVERRIDE 4
249 #define IPTOS_PREC_FLASH 3
250 #define IPTOS_PREC_IMMEDIATE 2
251 #define IPTOS_PREC_PRIORITY 1
252 #define IPTOS_PREC_ROUTINE 0
255 #define IPOPT_COPY 0x80
257 #define IPOPT_CONTROL 0x00
258 #define IPOPT_RESERVED1 0x20
259 #define IPOPT_MEASUREMENT 0x40
260 #define IPOPT_RESERVED2 0x60
262 #define IPOPT_END (0 |IPOPT_CONTROL)
263 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
264 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
265 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
266 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
267 #define IPOPT_RR (7 |IPOPT_CONTROL)
268 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
269 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
270 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
272 /* IP option lengths */
273 #define IPOLEN_SEC 11
274 #define IPOLEN_LSRR_MIN 3
275 #define IPOLEN_TIMESTAMP_MIN 5
276 #define IPOLEN_RR_MIN 3
278 #define IPOLEN_SSRR_MIN 3
281 #define IPSEC_UNCLASSIFIED 0x0000
282 #define IPSEC_CONFIDENTIAL 0xF135
283 #define IPSEC_EFTO 0x789A
284 #define IPSEC_MMMM 0xBC4D
285 #define IPSEC_RESTRICTED 0xAF13
286 #define IPSEC_SECRET 0xD788
287 #define IPSEC_TOPSECRET 0x6BC5
288 #define IPSEC_RESERVED1 0x35E2
289 #define IPSEC_RESERVED2 0x9AF1
290 #define IPSEC_RESERVED3 0x4D78
291 #define IPSEC_RESERVED4 0x24BD
292 #define IPSEC_RESERVED5 0x135E
293 #define IPSEC_RESERVED6 0x89AF
294 #define IPSEC_RESERVED7 0xC4D6
295 #define IPSEC_RESERVED8 0xE26B
297 #define IPOPT_TS_TSONLY 0 /* timestamps only */
298 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
299 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
302 * defragmentation of IPv4
304 static GHashTable *ip_fragment_table = NULL;
307 ip_defragment_init(void)
309 fragment_table_init(&ip_fragment_table);
313 capture_ip(const u_char *pd, int offset, packet_counts *ld) {
314 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
318 switch (pd[offset + 9]) {
346 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
347 guint optlen, frame_data *fd, proto_tree *opt_tree)
349 proto_tree *field_tree = NULL;
352 static const value_string secl_vals[] = {
353 {IPSEC_UNCLASSIFIED, "Unclassified"},
354 {IPSEC_CONFIDENTIAL, "Confidential"},
355 {IPSEC_EFTO, "EFTO" },
356 {IPSEC_MMMM, "MMMM" },
357 {IPSEC_RESTRICTED, "Restricted" },
358 {IPSEC_SECRET, "Secret" },
359 {IPSEC_TOPSECRET, "Top secret" },
360 {IPSEC_RESERVED1, "Reserved" },
361 {IPSEC_RESERVED2, "Reserved" },
362 {IPSEC_RESERVED3, "Reserved" },
363 {IPSEC_RESERVED4, "Reserved" },
364 {IPSEC_RESERVED5, "Reserved" },
365 {IPSEC_RESERVED6, "Reserved" },
366 {IPSEC_RESERVED7, "Reserved" },
367 {IPSEC_RESERVED8, "Reserved" },
370 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
371 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
374 val = tvb_get_ntohs(tvb, offset);
375 proto_tree_add_text(field_tree, tvb, offset, 2,
376 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
379 val = tvb_get_ntohs(tvb, offset);
380 proto_tree_add_text(field_tree, tvb, offset, 2,
381 "Compartments: %u", val);
384 proto_tree_add_text(field_tree, tvb, offset, 2,
385 "Handling restrictions: %c%c",
386 tvb_get_guint8(tvb, offset),
387 tvb_get_guint8(tvb, offset + 1));
390 proto_tree_add_text(field_tree, tvb, offset, 3,
391 "Transmission control code: %c%c%c",
392 tvb_get_guint8(tvb, offset),
393 tvb_get_guint8(tvb, offset + 1),
394 tvb_get_guint8(tvb, offset + 2));
398 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
399 guint optlen, frame_data *fd, proto_tree *opt_tree)
401 proto_tree *field_tree = NULL;
407 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
409 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
411 optoffset += 2; /* skip past type and length */
412 optlen -= 2; /* subtract size of type and length */
414 ptr = tvb_get_guint8(tvb, offset + optoffset);
415 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
416 "Pointer: %d%s", ptr,
417 ((ptr < 4) ? " (points before first address)" :
418 ((ptr & 3) ? " (points to middle of address)" : "")));
421 ptr--; /* ptr is 1-origin */
425 proto_tree_add_text(field_tree, tvb, offset, optlen,
426 "(suboption would go past end of option)");
430 /* Avoids alignment problems on many architectures. */
431 tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
433 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
435 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
436 ((optoffset == ptr) ? " <- (current)" : ""));
443 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
444 guint optlen, frame_data *fd, proto_tree *opt_tree)
446 proto_tree_add_text(opt_tree, tvb, offset, optlen,
447 "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
452 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
453 int offset, guint optlen, frame_data *fd, proto_tree *opt_tree)
455 proto_tree *field_tree = NULL;
460 static const value_string flag_vals[] = {
461 {IPOPT_TS_TSONLY, "Time stamps only" },
462 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
463 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
468 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
469 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
471 optoffset += 2; /* skip past type and length */
472 optlen -= 2; /* subtract size of type and length */
474 ptr = tvb_get_guint8(tvb, offset + optoffset);
475 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
476 "Pointer: %d%s", ptr,
477 ((ptr < 5) ? " (points before first address)" :
478 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
481 ptr--; /* ptr is 1-origin */
483 flg = tvb_get_guint8(tvb, offset + optoffset);
484 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
485 "Overflow: %u", flg >> 4);
487 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
488 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
493 if (flg == IPOPT_TS_TSANDADDR) {
495 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
496 "(suboption would go past end of option)");
499 tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
500 ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
502 proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
503 "Address = %s, time stamp = %u",
504 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
509 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
510 "(suboption would go past end of option)");
513 ts = tvb_get_ntohl(tvb, offset + optoffset);
515 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
516 "Time stamp = %u", ts);
523 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
524 guint optlen, frame_data *fd, proto_tree *opt_tree)
526 /* Router-Alert, as defined by RFC2113 */
527 int opt = tvb_get_ntohs(tvb, offset + 2);
528 static const value_string ra_opts[] = {
529 {0, "Every router examines packet"},
533 proto_tree_add_text(opt_tree, tvb, offset, optlen,
534 "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
538 static const ip_tcp_opt ipopts[] = {
561 dissect_ipopt_security
565 "Strict source route",
566 &ett_ip_option_route,
573 "Loose source route",
574 &ett_ip_option_route,
582 &ett_ip_option_route,
598 &ett_ip_option_timestamp,
600 IPOLEN_TIMESTAMP_MIN,
601 dissect_ipopt_timestamp
613 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
615 /* Dissect the IP or TCP options in a packet. */
617 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
618 const ip_tcp_opt *opttab, int nopts, int eol,
619 frame_data *fd, proto_tree *opt_tree)
622 const ip_tcp_opt *optp;
623 opt_len_type len_type;
626 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
627 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
628 int, guint, frame_data *, proto_tree *);
632 opt = tvb_get_guint8(tvb, offset);
633 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
634 if (optp->optcode == opt)
637 if (optp == &opttab[nopts]) {
638 /* We assume that the only NO_LENGTH options are EOL and NOP options,
639 so that we can treat unknown options as VARIABLE_LENGTH with a
640 minimum of 2, and at least be able to move on to the next option
641 by using the length in the option. */
642 optp = NULL; /* indicate that we don't know this option */
643 len_type = VARIABLE_LENGTH;
645 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
649 len_type = optp->len_type;
650 optlen = optp->optlen;
652 dissect = optp->dissect;
654 --length; /* account for type byte */
655 if (len_type != NO_LENGTH) {
656 /* Option has a length. Is it in the packet? */
658 /* Bogus - packet must at least include option code byte and
660 proto_tree_add_text(opt_tree, tvb, offset, 1,
661 "%s (length byte past end of options)", name);
664 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
665 --length; /* account for length byte */
667 /* Bogus - option length is too short to include option code and
669 proto_tree_add_text(opt_tree, tvb, offset, 2,
670 "%s (with too-short option length = %u byte%s)", name,
671 len, plurality(len, "", "s"));
673 } else if (len - 2 > length) {
674 /* Bogus - option goes past the end of the header. */
675 proto_tree_add_text(opt_tree, tvb, offset, length,
676 "%s (option length = %u byte%s says option goes past end of options)",
677 name, len, plurality(len, "", "s"));
679 } else if (len_type == FIXED_LENGTH && len != optlen) {
680 /* Bogus - option length isn't what it's supposed to be for this
682 proto_tree_add_text(opt_tree, tvb, offset, len,
683 "%s (with option length = %u byte%s; should be %u)", name,
684 len, plurality(len, "", "s"), optlen);
686 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
687 /* Bogus - option length is less than what it's supposed to be for
689 proto_tree_add_text(opt_tree, tvb, offset, len,
690 "%s (with option length = %u byte%s; should be >= %u)", name,
691 len, plurality(len, "", "s"), optlen);
695 proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
696 name, len, plurality(len, "", "s"));
698 if (dissect != NULL) {
699 /* Option has a dissector. */
700 (*dissect)(optp, tvb, offset, len, fd, opt_tree);
702 /* Option has no data, hence no dissector. */
703 proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
706 len -= 2; /* subtract size of type and length */
711 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
719 static const value_string dscp_vals[] = {
720 { IPDSFIELD_DSCP_DEFAULT, "Default" },
721 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
722 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
723 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
724 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
725 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
726 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
727 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
728 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
729 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
730 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
731 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
732 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
733 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
734 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
735 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
736 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
737 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
738 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
739 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
740 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
743 static const value_string precedence_vals[] = {
744 { IPTOS_PREC_ROUTINE, "routine" },
745 { IPTOS_PREC_PRIORITY, "priority" },
746 { IPTOS_PREC_IMMEDIATE, "immediate" },
747 { IPTOS_PREC_FLASH, "flash" },
748 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
749 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
750 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
751 { IPTOS_PREC_NETCONTROL, "network control" },
754 static const value_string iptos_vals[] = {
755 { IPTOS_NONE, "None" },
756 { IPTOS_LOWCOST, "Minimize cost" },
757 { IPTOS_RELIABILITY, "Maximize reliability" },
758 { IPTOS_THROUGHPUT, "Maximize throughput" },
759 { IPTOS_LOWDELAY, "Minimize delay" },
760 { IPTOS_SECURITY, "Maximize security" },
764 static const true_false_string tos_set_low = {
769 static const true_false_string tos_set_high = {
774 static const true_false_string flags_set_truth = {
779 static guint16 ip_checksum(const guint8 *ptr, int len)
783 cksum_vec[0].ptr = ptr;
784 cksum_vec[0].len = len;
785 return in_cksum(&cksum_vec[0], 1);
789 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
792 proto_tree *ip_tree = NULL, *field_tree;
795 guint hlen, optlen, len, payload_len, reported_payload_len;
800 fragment_data *ipfd_head;
803 gboolean must_restore_pi = FALSE;
804 gboolean update_col_info = TRUE;
806 if (check_col(pinfo->fd, COL_PROTOCOL))
807 col_set_str(pinfo->fd, COL_PROTOCOL, "IP");
808 if (check_col(pinfo->fd, COL_INFO))
809 col_clear(pinfo->fd, COL_INFO);
811 /* Avoids alignment problems on many architectures. */
812 tvb_memcpy(tvb, (guint8 *)&iph, offset, sizeof(e_ip));
813 iph.ip_len = ntohs(iph.ip_len);
814 iph.ip_id = ntohs(iph.ip_id);
815 iph.ip_off = ntohs(iph.ip_off);
816 iph.ip_sum = ntohs(iph.ip_sum);
818 /* Length of payload handed to us. */
819 reported_payload_len = tvb_reported_length(tvb);
820 payload_len = tvb_length(tvb);
822 /* Length of IP datagram. */
825 if (len < reported_payload_len) {
826 /* Adjust the length of this tvbuff to include only the IP datagram.
827 Our caller may use that to determine how much of its packet
829 tvb_set_reported_length(tvb, len);
831 /* Shrink the total payload by the amount of padding. */
832 padding = reported_payload_len - len;
833 if (pinfo->len >= padding)
834 pinfo->len -= padding;
836 /* Shrink the captured payload by the amount of padding in the
837 captured payload (which may be less than the amount of padding,
838 as the padding may not have been captured). */
839 if (len < payload_len) {
840 padding = payload_len - len;
841 if (pinfo->captured_len >= padding)
842 pinfo->captured_len -= padding;
846 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
849 if (ip_summary_in_tree && hlen >= IPH_MIN_LEN) {
850 ti = proto_tree_add_protocol_format(tree, proto_ip, tvb, offset, hlen,
851 "Internet Protocol, Src Addr: %s (%s), Dst Addr: %s (%s)",
852 get_hostname(iph.ip_src), ip_to_str((guint8 *) &iph.ip_src),
853 get_hostname(iph.ip_dst), ip_to_str((guint8 *) &iph.ip_dst));
855 ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
857 ip_tree = proto_item_add_subtree(ti, ett_ip);
860 if (hlen < IPH_MIN_LEN) {
861 if (check_col(pinfo->fd, COL_INFO))
862 col_add_fstr(pinfo->fd, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
865 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
866 "Header length: %u bytes (bogus, must be at least %u)", hlen,
873 * Compute the checksum of the IP header.
875 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
878 proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1, hi_nibble(iph.ip_v_hl));
879 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
880 "Header length: %u bytes", hlen);
882 if (g_ip_dscp_actif) {
883 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph.ip_tos,
884 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph.ip_tos,
885 IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
886 "Unknown DSCP"),IPDSFIELD_ECN(iph.ip_tos));
888 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
889 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph.ip_tos);
890 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph.ip_tos);
891 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph.ip_tos);
893 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph.ip_tos,
894 "Type of service: 0x%02x (%s)", iph.ip_tos,
895 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
897 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
898 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph.ip_tos);
899 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph.ip_tos);
900 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph.ip_tos);
901 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph.ip_tos);
902 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph.ip_tos);
904 proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph.ip_len);
905 proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph.ip_id);
907 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
908 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
909 field_tree = proto_item_add_subtree(tf, ett_ip_off);
910 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
911 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
913 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
914 (iph.ip_off & IP_OFFSET)*8);
916 proto_tree_add_uint(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, iph.ip_ttl);
917 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph.ip_p,
918 "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
921 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
922 "Header checksum: 0x%04x (correct)", iph.ip_sum);
925 proto_tree_add_item_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
926 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
927 "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph.ip_sum,
928 in_cksum_shouldbe(iph.ip_sum, ipsum));
931 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, iph.ip_src);
932 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, iph.ip_dst);
933 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, iph.ip_src);
934 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, iph.ip_dst);
936 /* Decode IP options, if any. */
937 if (hlen > sizeof (e_ip)) {
938 /* There's more than just the fixed-length header. Decode the
940 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
941 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
942 "Options: (%u bytes)", optlen);
943 field_tree = proto_item_add_subtree(tf, ett_ip_options);
944 dissect_ip_tcp_options(tvb, offset + 20, optlen,
945 ipopts, N_IP_OPTS, IPOPT_END, pinfo->fd, field_tree);
949 pinfo->ipproto = iph.ip_p;
951 pinfo->iplen = iph.ip_len;
953 pinfo->iphdrlen = lo_nibble(iph.ip_v_hl);
955 SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
956 SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
957 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
958 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
960 /* Skip over header + options */
962 nxt = iph.ip_p; /* XXX - what if this isn't the same for all fragments? */
964 /* If ip_defragment is on and this is a fragment, then just add the fragment
967 if (ip_defragment && (iph.ip_off & (IP_MF|IP_OFFSET))) {
968 /* We're reassembling, and this is part of a fragmented datagram.
969 Add the fragment to the hash table if the checksum is ok
970 and the frame isn't truncated. */
971 if ((ipsum==0) && (tvb_reported_length(tvb) <= tvb_length(tvb))) {
972 ipfd_head = fragment_add(tvb, offset, pinfo, iph.ip_id,
974 (iph.ip_off & IP_OFFSET)*8,
975 pinfo->iplen - (pinfo->iphdrlen*4),
981 if (ipfd_head != NULL) {
986 /* OK, we have the complete reassembled payload. */
987 /* show all fragments */
988 fi = proto_tree_add_item(ip_tree, hf_ip_fragments,
990 ft = proto_item_add_subtree(fi, ett_ip_fragments);
991 for (ipfd=ipfd_head->next; ipfd; ipfd=ipfd->next){
992 if (ipfd->flags & (FD_OVERLAP|FD_OVERLAPCONFLICT
993 |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
994 /* this fragment has some flags set, create a subtree
995 * for it and display the flags.
997 proto_tree *fet=NULL;
998 proto_item *fei=NULL;
1001 if (ipfd->flags & (FD_OVERLAPCONFLICT
1002 |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
1003 hf = hf_ip_fragment_error;
1005 hf = hf_ip_fragment;
1007 fei = proto_tree_add_none_format(ft, hf,
1009 "Frame:%d payload:%d-%d",
1012 ipfd->offset+ipfd->len-1
1014 fet = proto_item_add_subtree(fei, ett_ip_fragment);
1015 if (ipfd->flags&FD_OVERLAP) {
1016 proto_tree_add_boolean(fet,
1017 hf_ip_fragment_overlap, tvb, 0, 0,
1020 if (ipfd->flags&FD_OVERLAPCONFLICT) {
1021 proto_tree_add_boolean(fet,
1022 hf_ip_fragment_overlap_conflict, tvb, 0, 0,
1025 if (ipfd->flags&FD_MULTIPLETAILS) {
1026 proto_tree_add_boolean(fet,
1027 hf_ip_fragment_multiple_tails, tvb, 0, 0,
1030 if (ipfd->flags&FD_TOOLONGFRAGMENT) {
1031 proto_tree_add_boolean(fet,
1032 hf_ip_fragment_too_long_fragment, tvb, 0, 0,
1036 /* nothing of interest for this fragment */
1037 proto_tree_add_none_format(ft, hf_ip_fragment,
1039 "Frame:%d payload:%d-%d",
1042 ipfd->offset+ipfd->len-1
1046 if (ipfd_head->flags & (FD_OVERLAPCONFLICT
1047 |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
1048 if (check_col(pinfo->fd, COL_INFO)) {
1049 col_set_str(pinfo->fd, COL_INFO, "[Illegal fragments]");
1050 update_col_info = FALSE;
1054 /* Allocate a new tvbuff, referring to the reassembled payload. */
1055 next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen,
1056 ipfd_head->datalen, "Reassembled");
1058 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
1059 were handed refers, so it'll get cleaned up when that tvbuff
1061 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1063 /* Add the defragmented data to the data source list. */
1064 pinfo->fd->data_src = g_slist_append(pinfo->fd->data_src, next_tvb);
1066 /* It's not fragmented. */
1067 pinfo->fragmented = FALSE;
1069 /* Save the current value of "pi", and adjust certain fields to
1070 reflect the new tvbuff. */
1072 pi.compat_top_tvb = next_tvb;
1073 pi.len = tvb_reported_length(next_tvb);
1074 pi.captured_len = tvb_length(next_tvb);
1075 must_restore_pi = TRUE;
1077 /* We don't have the complete reassembled payload. */
1081 /* If this is the first fragment, dissect its contents, otherwise
1082 just show it as a fragment.
1084 XXX - if we eventually don't save the reassembled contents of all
1085 fragmented datagrams, we may want to always reassemble. */
1086 if (iph.ip_off & IP_OFFSET) {
1087 /* Not the first fragment - don't dissect it. */
1090 /* First fragment, or not fragmented. Dissect what we have here. */
1092 /* Get a tvbuff for the payload. */
1093 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1096 * If this is the first fragment, but not the only fragment,
1097 * tell the next protocol that.
1099 if (iph.ip_off & IP_MF)
1100 pinfo->fragmented = TRUE;
1102 pinfo->fragmented = FALSE;
1106 if (next_tvb == NULL) {
1107 /* Just show this as a fragment. */
1108 if (check_col(pinfo->fd, COL_INFO))
1109 col_add_fstr(pinfo->fd, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1110 ipprotostr(iph.ip_p), iph.ip_p, (iph.ip_off & IP_OFFSET) * 8);
1111 dissect_data(tvb, offset, pinfo, tree);
1113 /* As we haven't reassembled anything, we haven't changed "pi", so
1114 we don't have to restore it. */
1118 /* Hand off to the next protocol.
1120 XXX - setting the columns only after trying various dissectors means
1121 that if one of those dissectors throws an exception, the frame won't
1122 even be labelled as an IP frame; ideally, if a frame being dissected
1123 throws an exception, it'll be labelled as a mangled frame of the
1124 type in question. */
1125 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
1126 /* Unknown protocol */
1127 if (update_col_info) {
1128 if (check_col(pinfo->fd, COL_INFO))
1129 col_add_fstr(pinfo->fd, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
1131 dissect_data(next_tvb, 0, pinfo, tree);
1134 if (must_restore_pi)
1139 static const gchar *unreach_str[] = {"Network unreachable",
1141 "Protocol unreachable",
1143 "Fragmentation needed",
1144 "Source route failed",
1145 "Destination network unknown",
1146 "Destination host unknown",
1147 "Source host isolated",
1148 "Network administratively prohibited",
1149 "Host administratively prohibited",
1150 "Network unreachable for TOS",
1151 "Host unreachable for TOS",
1152 "Communication administratively filtered",
1153 "Host precedence violation",
1154 "Precedence cutoff in effect"};
1156 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1158 static const gchar *redir_str[] = {"Redirect for network",
1159 "Redirect for host",
1160 "Redirect for TOS and network",
1161 "Redirect for TOS and host"};
1163 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1165 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
1166 "TTL equals 0 during reassembly"};
1168 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1170 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1172 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1175 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1177 proto_tree *icmp_tree;
1181 guint length, reported_length;
1182 guint16 cksum, computed_cksum;
1183 gchar type_str[64], code_str[64] = "";
1184 guint8 num_addrs = 0;
1185 guint8 addr_entry_size = 0;
1188 if (check_col(pinfo->fd, COL_PROTOCOL))
1189 col_set_str(pinfo->fd, COL_PROTOCOL, "ICMP");
1190 if (check_col(pinfo->fd, COL_INFO))
1191 col_clear(pinfo->fd, COL_INFO);
1193 /* To do: check for runts, errs, etc. */
1194 icmp_type = tvb_get_guint8(tvb, 0);
1195 icmp_code = tvb_get_guint8(tvb, 1);
1196 cksum = tvb_get_ntohs(tvb, 2);
1198 switch (icmp_type) {
1199 case ICMP_ECHOREPLY:
1200 strcpy(type_str, "Echo (ping) reply");
1203 strcpy(type_str, "Destination unreachable");
1204 if (icmp_code < N_UNREACH) {
1205 sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1207 strcpy(code_str, "(Unknown - error?)");
1210 case ICMP_SOURCEQUENCH:
1211 strcpy(type_str, "Source quench (flow control)");
1214 strcpy(type_str, "Redirect");
1215 if (icmp_code < N_REDIRECT) {
1216 sprintf(code_str, "(%s)", redir_str[icmp_code]);
1218 strcpy(code_str, "(Unknown - error?)");
1222 strcpy(type_str, "Echo (ping) request");
1224 case ICMP_RTRADVERT:
1225 strcpy(type_str, "Router advertisement");
1227 case ICMP_RTRSOLICIT:
1228 strcpy(type_str, "Router solicitation");
1231 strcpy(type_str, "Time-to-live exceeded");
1232 if (icmp_code < N_TIMXCEED) {
1233 sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1235 strcpy(code_str, "(Unknown - error?)");
1238 case ICMP_PARAMPROB:
1239 strcpy(type_str, "Parameter problem");
1240 if (icmp_code < N_PARAMPROB) {
1241 sprintf(code_str, "(%s)", par_str[icmp_code]);
1243 strcpy(code_str, "(Unknown - error?)");
1247 strcpy(type_str, "Timestamp request");
1249 case ICMP_TSTAMPREPLY:
1250 strcpy(type_str, "Timestamp reply");
1253 strcpy(type_str, "Information request");
1255 case ICMP_IREQREPLY:
1256 strcpy(type_str, "Information reply");
1259 strcpy(type_str, "Address mask request");
1261 case ICMP_MASKREPLY:
1262 strcpy(type_str, "Address mask reply");
1265 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1268 if (check_col(pinfo->fd, COL_INFO))
1269 col_add_str(pinfo->fd, COL_INFO, type_str);
1272 length = tvb_length(tvb);
1273 reported_length = tvb_reported_length(tvb);
1274 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1275 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1276 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1279 icmp_type, type_str);
1280 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1283 icmp_code, code_str);
1285 if (!pinfo->fragmented && length >= reported_length) {
1286 /* The packet isn't part of a fragmented datagram and isn't
1287 truncated, so we can checksum it. */
1289 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1291 if (computed_cksum == 0) {
1292 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1294 "Checksum: 0x%04x (correct)", cksum);
1296 proto_tree_add_item_hidden(icmp_tree, hf_icmp_checksum_bad,
1298 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1300 "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1301 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1304 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1307 /* Decode the second 4 bytes of the packet. */
1308 switch (icmp_type) {
1309 case ICMP_ECHOREPLY:
1312 case ICMP_TSTAMPREPLY:
1314 case ICMP_IREQREPLY:
1316 case ICMP_MASKREPLY:
1317 proto_tree_add_text(icmp_tree, tvb, 4, 2, "Identifier: 0x%04x",
1318 tvb_get_ntohs(tvb, 4));
1319 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Sequence number: %02x:%02x",
1320 tvb_get_guint8(tvb, 6), tvb_get_guint8(tvb, 7));
1324 switch (icmp_code) {
1325 case ICMP_FRAG_NEEDED:
1326 proto_tree_add_text(icmp_tree, tvb, 6, 2, "MTU of next hop: %u",
1327 tvb_get_ntohs(tvb, 6));
1332 case ICMP_RTRADVERT:
1333 num_addrs = tvb_get_guint8(tvb, 4);
1334 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1336 addr_entry_size = tvb_get_guint8(tvb, 5);
1337 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1339 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1340 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1343 case ICMP_PARAMPROB:
1344 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1345 tvb_get_guint8(tvb, 4));
1349 proto_tree_add_text(icmp_tree, tvb, 4, 4, "Gateway address: %s",
1350 ip_to_str(tvb_get_ptr(tvb, 4, 4)));
1354 /* Decode the additional information in the packet. */
1355 switch (icmp_type) {
1358 case ICMP_PARAMPROB:
1359 case ICMP_SOURCEQUENCH:
1361 /* Decode the IP header and first 64 bits of data from the
1364 XXX - for now, just display it as data; not all dissection
1365 routines can handle a short packet without exploding. */
1366 dissect_data(tvb, 8, pinfo, icmp_tree);
1369 case ICMP_ECHOREPLY:
1371 dissect_data(tvb, 8, pinfo, icmp_tree);
1374 case ICMP_RTRADVERT:
1375 if (addr_entry_size == 2) {
1376 for (i = 0; i < num_addrs; i++) {
1377 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1378 "Router address: %s",
1379 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1380 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1381 "Preference level: %u", tvb_get_ntohl(tvb, 12 + (i*8)));
1384 dissect_data(tvb, 8, pinfo, icmp_tree);
1388 case ICMP_TSTAMPREPLY:
1389 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1390 tvb_get_ntohl(tvb, 8));
1391 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1392 tvb_get_ntohl(tvb, 12));
1393 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1394 tvb_get_ntohl(tvb, 16));
1398 case ICMP_MASKREPLY:
1399 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1400 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1407 proto_register_ip(void)
1409 static hf_register_info hf[] = {
1412 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1416 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1420 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1423 { &hf_ip_dsfield_dscp,
1424 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1425 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1428 { &hf_ip_dsfield_ect,
1429 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1433 { &hf_ip_dsfield_ce,
1434 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1439 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1442 { &hf_ip_tos_precedence,
1443 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1448 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1452 { &hf_ip_tos_throughput,
1453 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1457 { &hf_ip_tos_reliability,
1458 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1463 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1468 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1472 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1476 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1480 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1484 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1488 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1492 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1496 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1499 { &hf_ip_frag_offset,
1500 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1504 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1508 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1512 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1515 { &hf_ip_checksum_bad,
1516 { "Bad Header checksum", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1519 { &hf_ip_fragment_overlap,
1520 { "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1521 "Fragment overlaps with other fragments", HFILL }},
1523 { &hf_ip_fragment_overlap_conflict,
1524 { "Conflicting data in fragment overlap", "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1525 "Overlapping fragments contained conflicting data", HFILL }},
1527 { &hf_ip_fragment_multiple_tails,
1528 { "Multiple tail fragments found", "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1529 "Several tails were found when defragmenting the packet", HFILL }},
1531 { &hf_ip_fragment_too_long_fragment,
1532 { "Fragment too long", "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1533 "Fragment contained data past end of packet", HFILL }},
1535 { &hf_ip_fragment_error,
1536 { "Defragmentation error", "ip.fragment.error", FT_NONE, BASE_NONE, NULL, 0x0,
1537 "Defragmentation error due to illegal fragments", HFILL }},
1540 { "IP Fragment", "ip.fragment", FT_NONE, BASE_NONE, NULL, 0x0,
1541 "IP Fragment", HFILL }},
1544 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1545 "IP Fragments", HFILL }},
1547 static gint *ett[] = {
1554 &ett_ip_option_route,
1555 &ett_ip_option_timestamp,
1559 module_t *ip_module;
1561 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1562 proto_register_field_array(proto_ip, hf, array_length(hf));
1563 proto_register_subtree_array(ett, array_length(ett));
1565 /* subdissector code */
1566 ip_dissector_table = register_dissector_table("ip.proto");
1568 /* Register configuration options */
1569 ip_module = prefs_register_protocol(proto_ip, NULL);
1570 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1571 "Decode IPv4 TOS field as DiffServ field",
1572 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1574 prefs_register_bool_preference(ip_module, "defragment",
1575 "Reassemble fragmented IP datagrams",
1576 "Whether fragmented IP datagrams should be reassembled",
1578 prefs_register_bool_preference(ip_module, "ip_summary_in_tree",
1579 "Show IP summary in protocol tree",
1580 "Whether the IP summary line should be shown in the protocol tree",
1581 &ip_summary_in_tree);
1583 register_dissector("ip", dissect_ip, proto_ip);
1584 register_init_routine(ip_defragment_init);
1588 proto_reg_handoff_ip(void)
1590 dissector_add("ethertype", ETHERTYPE_IP, dissect_ip, proto_ip);
1591 dissector_add("ppp.protocol", PPP_IP, dissect_ip, proto_ip);
1592 dissector_add("ppp.protocol", ETHERTYPE_IP, dissect_ip, proto_ip);
1593 dissector_add("gre.proto", ETHERTYPE_IP, dissect_ip, proto_ip);
1594 dissector_add("gre.proto", GRE_WCCP, dissect_ip, proto_ip);
1595 dissector_add("llc.dsap", SAP_IP, dissect_ip, proto_ip);
1596 dissector_add("ip.proto", IP_PROTO_IPIP, dissect_ip, proto_ip);
1597 dissector_add("null.type", BSD_AF_INET, dissect_ip, proto_ip);
1598 dissector_add("chdlctype", ETHERTYPE_IP, dissect_ip, proto_ip);
1599 dissector_add("fr.ietf", NLPID_IP, dissect_ip, proto_ip);
1603 proto_register_icmp(void)
1605 static hf_register_info hf[] = {
1608 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1612 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1615 { &hf_icmp_checksum,
1616 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1619 { &hf_icmp_checksum_bad,
1620 { "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1623 static gint *ett[] = {
1627 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
1629 proto_register_field_array(proto_icmp, hf, array_length(hf));
1630 proto_register_subtree_array(ett, array_length(ett));
1634 proto_reg_handoff_icmp(void)
1636 dissector_add("ip.proto", IP_PROTO_ICMP, dissect_icmp, proto_icmp);