2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.201 2003/11/13 08:16:52 sahlberg 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;
138 static int hf_icmp_ident = -1;
139 static int hf_icmp_seq_num = -1;
140 static int hf_icmp_mtu = -1;
141 static int hf_icmp_redir_gw = -1;
145 static int hf_icmp_mip_type = -1;
146 static int hf_icmp_mip_length = -1;
147 static int hf_icmp_mip_prefix_length = -1;
148 static int hf_icmp_mip_seq = -1;
149 static int hf_icmp_mip_life = -1;
150 static int hf_icmp_mip_flags = -1;
151 static int hf_icmp_mip_r = -1;
152 static int hf_icmp_mip_b = -1;
153 static int hf_icmp_mip_h = -1;
154 static int hf_icmp_mip_f = -1;
155 static int hf_icmp_mip_m = -1;
156 static int hf_icmp_mip_g = -1;
157 static int hf_icmp_mip_v = -1;
158 static int hf_icmp_mip_res = -1;
159 static int hf_icmp_mip_reserved = -1;
160 static int hf_icmp_mip_coa = -1;
161 static int hf_icmp_mip_challenge = -1;
163 static gint ett_icmp = -1;
164 static gint ett_icmp_mip = -1;
165 static gint ett_icmp_mip_flags = -1;
167 /* ICMP definitions */
169 #define ICMP_ECHOREPLY 0
170 #define ICMP_UNREACH 3
171 #define ICMP_SOURCEQUENCH 4
172 #define ICMP_REDIRECT 5
174 #define ICMP_RTRADVERT 9
175 #define ICMP_RTRSOLICIT 10
176 #define ICMP_TIMXCEED 11
177 #define ICMP_PARAMPROB 12
178 #define ICMP_TSTAMP 13
179 #define ICMP_TSTAMPREPLY 14
181 #define ICMP_IREQREPLY 16
182 #define ICMP_MASKREQ 17
183 #define ICMP_MASKREPLY 18
185 /* ICMP UNREACHABLE */
187 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
188 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
189 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
190 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
191 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
192 #define ICMP_SR_FAILED 5 /* Source Route failed */
193 #define ICMP_NET_UNKNOWN 6
194 #define ICMP_HOST_UNKNOWN 7
195 #define ICMP_HOST_ISOLATED 8
196 #define ICMP_NET_ANO 9
197 #define ICMP_HOST_ANO 10
198 #define ICMP_NET_UNR_TOS 11
199 #define ICMP_HOST_UNR_TOS 12
200 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
201 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
202 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
205 /* IP structs and definitions */
207 /* Offsets of fields within an IP header. */
219 /* Minimum IP header length. */
220 #define IPH_MIN_LEN 20
223 #define IP_CE 0x8000 /* Flag: "Congestion" */
224 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
225 #define IP_MF 0x2000 /* Flag: "More Fragments" */
226 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
228 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
229 #define IPDSFIELD_DSCP_MASK 0xFC
230 #define IPDSFIELD_ECN_MASK 0x03
231 #define IPDSFIELD_DSCP_SHIFT 2
232 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
233 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
234 #define IPDSFIELD_DSCP_DEFAULT 0x00
235 #define IPDSFIELD_DSCP_CS1 0x08
236 #define IPDSFIELD_DSCP_CS2 0x10
237 #define IPDSFIELD_DSCP_CS3 0x18
238 #define IPDSFIELD_DSCP_CS4 0x20
239 #define IPDSFIELD_DSCP_CS5 0x28
240 #define IPDSFIELD_DSCP_CS6 0x30
241 #define IPDSFIELD_DSCP_CS7 0x38
242 #define IPDSFIELD_DSCP_AF11 0x0A
243 #define IPDSFIELD_DSCP_AF12 0x0C
244 #define IPDSFIELD_DSCP_AF13 0x0E
245 #define IPDSFIELD_DSCP_AF21 0x12
246 #define IPDSFIELD_DSCP_AF22 0x14
247 #define IPDSFIELD_DSCP_AF23 0x16
248 #define IPDSFIELD_DSCP_AF31 0x1A
249 #define IPDSFIELD_DSCP_AF32 0x1C
250 #define IPDSFIELD_DSCP_AF33 0x1E
251 #define IPDSFIELD_DSCP_AF41 0x22
252 #define IPDSFIELD_DSCP_AF42 0x24
253 #define IPDSFIELD_DSCP_AF43 0x26
254 #define IPDSFIELD_DSCP_EF 0x2E
255 #define IPDSFIELD_ECT_MASK 0x02
256 #define IPDSFIELD_CE_MASK 0x01
258 /* IP TOS, superseded by the DS Field, RFC 2474. */
259 #define IPTOS_TOS_MASK 0x1E
260 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
261 #define IPTOS_NONE 0x00
262 #define IPTOS_LOWCOST 0x02
263 #define IPTOS_RELIABILITY 0x04
264 #define IPTOS_THROUGHPUT 0x08
265 #define IPTOS_LOWDELAY 0x10
266 #define IPTOS_SECURITY 0x1E
268 #define IPTOS_PREC_MASK 0xE0
269 #define IPTOS_PREC_SHIFT 5
270 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
271 #define IPTOS_PREC_NETCONTROL 7
272 #define IPTOS_PREC_INTERNETCONTROL 6
273 #define IPTOS_PREC_CRITIC_ECP 5
274 #define IPTOS_PREC_FLASHOVERRIDE 4
275 #define IPTOS_PREC_FLASH 3
276 #define IPTOS_PREC_IMMEDIATE 2
277 #define IPTOS_PREC_PRIORITY 1
278 #define IPTOS_PREC_ROUTINE 0
281 #define IPOPT_COPY 0x80
283 #define IPOPT_CONTROL 0x00
284 #define IPOPT_RESERVED1 0x20
285 #define IPOPT_MEASUREMENT 0x40
286 #define IPOPT_RESERVED2 0x60
288 #define IPOPT_END (0 |IPOPT_CONTROL)
289 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
290 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
291 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
292 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
293 #define IPOPT_RR (7 |IPOPT_CONTROL)
294 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
295 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
296 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
298 /* IP option lengths */
299 #define IPOLEN_SEC 11
300 #define IPOLEN_LSRR_MIN 3
301 #define IPOLEN_TIMESTAMP_MIN 5
302 #define IPOLEN_RR_MIN 3
304 #define IPOLEN_SSRR_MIN 3
307 #define IPSEC_UNCLASSIFIED 0x0000
308 #define IPSEC_CONFIDENTIAL 0xF135
309 #define IPSEC_EFTO 0x789A
310 #define IPSEC_MMMM 0xBC4D
311 #define IPSEC_RESTRICTED 0xAF13
312 #define IPSEC_SECRET 0xD788
313 #define IPSEC_TOPSECRET 0x6BC5
314 #define IPSEC_RESERVED1 0x35E2
315 #define IPSEC_RESERVED2 0x9AF1
316 #define IPSEC_RESERVED3 0x4D78
317 #define IPSEC_RESERVED4 0x24BD
318 #define IPSEC_RESERVED5 0x135E
319 #define IPSEC_RESERVED6 0x89AF
320 #define IPSEC_RESERVED7 0xC4D6
321 #define IPSEC_RESERVED8 0xE26B
323 #define IPOPT_TS_TSONLY 0 /* timestamps only */
324 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
325 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
328 * defragmentation of IPv4
330 static GHashTable *ip_fragment_table = NULL;
331 static GHashTable *ip_reassembled_table = NULL;
334 ip_defragment_init(void)
336 fragment_table_init(&ip_fragment_table);
337 reassembled_table_init(&ip_reassembled_table);
341 capture_ip(const guchar *pd, int offset, int len, packet_counts *ld) {
342 if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
346 switch (pd[offset + 9]) {
357 case IP_PROTO_ICMPV6: /* XXX - separate counters? */
375 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
376 guint optlen, packet_info *pinfo _U_,
377 proto_tree *opt_tree)
379 proto_tree *field_tree = NULL;
382 static const value_string secl_vals[] = {
383 {IPSEC_UNCLASSIFIED, "Unclassified"},
384 {IPSEC_CONFIDENTIAL, "Confidential"},
385 {IPSEC_EFTO, "EFTO" },
386 {IPSEC_MMMM, "MMMM" },
387 {IPSEC_RESTRICTED, "Restricted" },
388 {IPSEC_SECRET, "Secret" },
389 {IPSEC_TOPSECRET, "Top secret" },
390 {IPSEC_RESERVED1, "Reserved" },
391 {IPSEC_RESERVED2, "Reserved" },
392 {IPSEC_RESERVED3, "Reserved" },
393 {IPSEC_RESERVED4, "Reserved" },
394 {IPSEC_RESERVED5, "Reserved" },
395 {IPSEC_RESERVED6, "Reserved" },
396 {IPSEC_RESERVED7, "Reserved" },
397 {IPSEC_RESERVED8, "Reserved" },
400 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
401 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
404 val = tvb_get_ntohs(tvb, offset);
405 proto_tree_add_text(field_tree, tvb, offset, 2,
406 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
409 val = tvb_get_ntohs(tvb, offset);
410 proto_tree_add_text(field_tree, tvb, offset, 2,
411 "Compartments: %u", val);
414 proto_tree_add_text(field_tree, tvb, offset, 2,
415 "Handling restrictions: %c%c",
416 tvb_get_guint8(tvb, offset),
417 tvb_get_guint8(tvb, offset + 1));
420 proto_tree_add_text(field_tree, tvb, offset, 3,
421 "Transmission control code: %c%c%c",
422 tvb_get_guint8(tvb, offset),
423 tvb_get_guint8(tvb, offset + 1),
424 tvb_get_guint8(tvb, offset + 2));
428 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
429 guint optlen, packet_info *pinfo _U_,
430 proto_tree *opt_tree)
432 proto_tree *field_tree = NULL;
438 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
440 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
442 optoffset += 2; /* skip past type and length */
443 optlen -= 2; /* subtract size of type and length */
445 ptr = tvb_get_guint8(tvb, offset + optoffset);
446 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
447 "Pointer: %d%s", ptr,
448 ((ptr < 4) ? " (points before first address)" :
449 ((ptr & 3) ? " (points to middle of address)" : "")));
452 ptr--; /* ptr is 1-origin */
456 proto_tree_add_text(field_tree, tvb, offset, optlen,
457 "(suboption would go past end of option)");
461 /* Avoids alignment problems on many architectures. */
462 tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
464 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
466 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
467 ((optoffset == ptr) ? " <- (current)" : ""));
474 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
475 guint optlen, packet_info *pinfo _U_,
476 proto_tree *opt_tree)
478 proto_tree_add_text(opt_tree, tvb, offset, optlen,
479 "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
484 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
485 int offset, guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
487 proto_tree *field_tree = NULL;
492 static const value_string flag_vals[] = {
493 {IPOPT_TS_TSONLY, "Time stamps only" },
494 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
495 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
500 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
501 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
503 optoffset += 2; /* skip past type and length */
504 optlen -= 2; /* subtract size of type and length */
506 ptr = tvb_get_guint8(tvb, offset + optoffset);
507 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
508 "Pointer: %d%s", ptr,
509 ((ptr < 5) ? " (points before first address)" :
510 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
513 ptr--; /* ptr is 1-origin */
515 flg = tvb_get_guint8(tvb, offset + optoffset);
516 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
517 "Overflow: %u", flg >> 4);
519 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
520 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
525 if (flg == IPOPT_TS_TSANDADDR) {
527 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
528 "(suboption would go past end of option)");
531 tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
532 ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
534 proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
535 "Address = %s, time stamp = %u",
536 ((addr == 0) ? "-" : (char *)get_hostname(addr)),
541 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
542 "(suboption would go past end of option)");
545 ts = tvb_get_ntohl(tvb, offset + optoffset);
547 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
548 "Time stamp = %u", ts);
555 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
556 guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
558 /* Router-Alert, as defined by RFC2113 */
559 int opt = tvb_get_ntohs(tvb, offset + 2);
560 static const value_string ra_opts[] = {
561 {0, "Every router examines packet"},
565 proto_tree_add_text(opt_tree, tvb, offset, optlen,
566 "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
570 static const ip_tcp_opt ipopts[] = {
593 dissect_ipopt_security
597 "Strict source route",
598 &ett_ip_option_route,
605 "Loose source route",
606 &ett_ip_option_route,
614 &ett_ip_option_route,
630 &ett_ip_option_timestamp,
632 IPOLEN_TIMESTAMP_MIN,
633 dissect_ipopt_timestamp
645 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
647 /* Dissect the IP or TCP options in a packet. */
649 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
650 const ip_tcp_opt *opttab, int nopts, int eol,
651 packet_info *pinfo, proto_tree *opt_tree)
654 const ip_tcp_opt *optp;
655 opt_len_type len_type;
658 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
659 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
660 int, guint, packet_info *, proto_tree *);
664 opt = tvb_get_guint8(tvb, offset);
665 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
666 if (optp->optcode == opt)
669 if (optp == &opttab[nopts]) {
670 /* We assume that the only NO_LENGTH options are EOL and NOP options,
671 so that we can treat unknown options as VARIABLE_LENGTH with a
672 minimum of 2, and at least be able to move on to the next option
673 by using the length in the option. */
674 optp = NULL; /* indicate that we don't know this option */
675 len_type = VARIABLE_LENGTH;
677 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
681 len_type = optp->len_type;
682 optlen = optp->optlen;
684 dissect = optp->dissect;
686 --length; /* account for type byte */
687 if (len_type != NO_LENGTH) {
688 /* Option has a length. Is it in the packet? */
690 /* Bogus - packet must at least include option code byte and
692 proto_tree_add_text(opt_tree, tvb, offset, 1,
693 "%s (length byte past end of options)", name);
696 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
697 --length; /* account for length byte */
699 /* Bogus - option length is too short to include option code and
701 proto_tree_add_text(opt_tree, tvb, offset, 2,
702 "%s (with too-short option length = %u byte%s)", name,
703 len, plurality(len, "", "s"));
705 } else if (len - 2 > length) {
706 /* Bogus - option goes past the end of the header. */
707 proto_tree_add_text(opt_tree, tvb, offset, length,
708 "%s (option length = %u byte%s says option goes past end of options)",
709 name, len, plurality(len, "", "s"));
711 } else if (len_type == FIXED_LENGTH && len != optlen) {
712 /* Bogus - option length isn't what it's supposed to be for this
714 proto_tree_add_text(opt_tree, tvb, offset, len,
715 "%s (with option length = %u byte%s; should be %u)", name,
716 len, plurality(len, "", "s"), optlen);
718 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
719 /* Bogus - option length is less than what it's supposed to be for
721 proto_tree_add_text(opt_tree, tvb, offset, len,
722 "%s (with option length = %u byte%s; should be >= %u)", name,
723 len, plurality(len, "", "s"), optlen);
727 proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
728 name, len, plurality(len, "", "s"));
730 if (dissect != NULL) {
731 /* Option has a dissector. */
732 (*dissect)(optp, tvb, offset, len, pinfo, opt_tree);
734 /* Option has no data, hence no dissector. */
735 proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
738 len -= 2; /* subtract size of type and length */
743 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
751 const value_string dscp_vals[] = {
752 { IPDSFIELD_DSCP_DEFAULT, "Default" },
753 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
754 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
755 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
756 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
757 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
758 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
759 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
760 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
761 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
762 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
763 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
764 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
765 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
766 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
767 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
768 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
769 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
770 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
771 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
772 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
775 static const value_string precedence_vals[] = {
776 { IPTOS_PREC_ROUTINE, "routine" },
777 { IPTOS_PREC_PRIORITY, "priority" },
778 { IPTOS_PREC_IMMEDIATE, "immediate" },
779 { IPTOS_PREC_FLASH, "flash" },
780 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
781 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
782 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
783 { IPTOS_PREC_NETCONTROL, "network control" },
786 static const value_string iptos_vals[] = {
787 { IPTOS_NONE, "None" },
788 { IPTOS_LOWCOST, "Minimize cost" },
789 { IPTOS_RELIABILITY, "Maximize reliability" },
790 { IPTOS_THROUGHPUT, "Maximize throughput" },
791 { IPTOS_LOWDELAY, "Minimize delay" },
792 { IPTOS_SECURITY, "Maximize security" },
796 static const true_false_string tos_set_low = {
801 static const true_false_string tos_set_high = {
806 static guint16 ip_checksum(const guint8 *ptr, int len)
810 cksum_vec[0].ptr = ptr;
811 cksum_vec[0].len = len;
812 return in_cksum(&cksum_vec[0], 1);
816 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
818 proto_tree *ip_tree = NULL, *field_tree;
819 proto_item *ti = NULL, *tf;
826 fragment_data *ipfd_head=NULL;
828 gboolean update_col_info = TRUE;
829 gboolean save_fragmented;
830 static e_ip eip_arr[4];
831 static int eip_current=0;
838 iph=&eip_arr[eip_current];
840 if (check_col(pinfo->cinfo, COL_PROTOCOL))
841 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
842 if (check_col(pinfo->cinfo, COL_INFO))
843 col_clear(pinfo->cinfo, COL_INFO);
845 iph->ip_v_hl = tvb_get_guint8(tvb, offset);
846 hlen = lo_nibble(iph->ip_v_hl) * 4; /* IP header length, in bytes */
849 ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
850 ip_tree = proto_item_add_subtree(ti, ett_ip);
852 proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1,
853 hi_nibble(iph->ip_v_hl));
856 if (hlen < IPH_MIN_LEN) {
857 if (check_col(pinfo->cinfo, COL_INFO))
858 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
861 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
862 "Header length: %u bytes (bogus, must be at least %u)", hlen,
869 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
870 "Header length: %u bytes", hlen);
873 iph->ip_tos = tvb_get_guint8(tvb, offset + 1);
875 if (g_ip_dscp_actif) {
876 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph->ip_tos,
877 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph->ip_tos,
878 IPDSFIELD_DSCP(iph->ip_tos), val_to_str(IPDSFIELD_DSCP(iph->ip_tos), dscp_vals,
879 "Unknown DSCP"),IPDSFIELD_ECN(iph->ip_tos));
881 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
882 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph->ip_tos);
883 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph->ip_tos);
884 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph->ip_tos);
886 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph->ip_tos,
887 "Type of service: 0x%02x (%s)", iph->ip_tos,
888 val_to_str( IPTOS_TOS(iph->ip_tos), iptos_vals, "Unknown") );
890 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
891 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph->ip_tos);
892 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph->ip_tos);
893 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph->ip_tos);
894 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph->ip_tos);
895 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph->ip_tos);
899 /* Length of IP datagram.
900 XXX - what if this is greater than the reported length of the
901 tvbuff? This could happen, for example, in an IP datagram
902 inside an ICMP datagram; we need to somehow let the
903 dissector we call know that, as it might want to avoid
904 doing its checksumming. */
905 iph->ip_len = tvb_get_ntohs(tvb, offset + 2);
907 /* Adjust the length of this tvbuff to include only the IP datagram. */
908 set_actual_length(tvb, iph->ip_len);
910 if (iph->ip_len < hlen) {
911 if (check_col(pinfo->cinfo, COL_INFO))
912 col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP length (%u, less than header length %u)",
915 proto_tree_add_uint_format(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len,
916 "Total length: %u bytes (bogus, less than header length %u)", iph->ip_len,
922 proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len);
924 iph->ip_id = tvb_get_ntohs(tvb, offset + 4);
926 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);
928 iph->ip_off = tvb_get_ntohs(tvb, offset + 6);
930 flags = (iph->ip_off & (IP_DF|IP_MF)) >> 12;
931 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
932 field_tree = proto_item_add_subtree(tf, ett_ip_off);
933 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
934 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
936 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
937 (iph->ip_off & IP_OFFSET)*8);
941 proto_tree_add_item(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, FALSE);
943 iph->ip_p = tvb_get_guint8(tvb, offset + 9);
945 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph->ip_p,
946 "Protocol: %s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
949 iph->ip_sum = tvb_get_ntohs(tvb, offset + 10);
952 * If we have the entire IP header available, check the checksum.
954 if (tvb_bytes_exist(tvb, offset, hlen)) {
955 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
958 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
959 "Header checksum: 0x%04x (correct)", iph->ip_sum);
962 proto_tree_add_boolean_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
963 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
964 "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph->ip_sum,
965 in_cksum_shouldbe(iph->ip_sum, ipsum));
971 proto_tree_add_uint(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum);
974 SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
975 SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
976 SET_ADDRESS(&iph->ip_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
978 memcpy(&addr, iph->ip_src.data, 4);
979 if (ip_summary_in_tree) {
980 proto_item_append_text(ti, ", Src Addr: %s (%s)",
981 get_hostname(addr), ip_to_str((guint8 *) iph->ip_src.data));
983 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, addr);
984 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, addr);
987 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
988 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
989 SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
992 memcpy(&addr, iph->ip_dst.data, 4);
993 if (ip_summary_in_tree) {
994 proto_item_append_text(ti, ", Dst Addr: %s (%s)",
995 get_hostname(addr), ip_to_str((guint8 *) iph->ip_dst.data));
997 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, addr);
998 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, addr);
1002 /* Decode IP options, if any. */
1003 if (hlen > IPH_MIN_LEN) {
1004 /* There's more than just the fixed-length header. Decode the
1006 optlen = hlen - IPH_MIN_LEN; /* length of options, in bytes */
1007 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
1008 "Options: (%u bytes)", optlen);
1009 field_tree = proto_item_add_subtree(tf, ett_ip_options);
1010 dissect_ip_tcp_options(tvb, offset + 20, optlen,
1011 ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
1015 pinfo->ipproto = iph->ip_p;
1017 pinfo->iplen = iph->ip_len;
1019 pinfo->iphdrlen = hlen;
1021 /* Skip over header + options */
1023 nxt = iph->ip_p; /* XXX - what if this isn't the same for all fragments? */
1025 /* If ip_defragment is on, this is a fragment, we have all the data
1026 * in the fragment, and the header checksum is valid, then just add
1027 * the fragment to the hashtable.
1029 save_fragmented = pinfo->fragmented;
1030 if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
1031 tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
1033 ipfd_head = fragment_add_check(tvb, offset, pinfo, iph->ip_id,
1035 ip_reassembled_table,
1036 (iph->ip_off & IP_OFFSET)*8,
1037 pinfo->iplen - pinfo->iphdrlen,
1038 iph->ip_off & IP_MF);
1040 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv4",
1041 ipfd_head, &ip_frag_items, &update_col_info, ip_tree);
1043 /* If this is the first fragment, dissect its contents, otherwise
1044 just show it as a fragment.
1046 XXX - if we eventually don't save the reassembled contents of all
1047 fragmented datagrams, we may want to always reassemble. */
1048 if (iph->ip_off & IP_OFFSET) {
1049 /* Not the first fragment - don't dissect it. */
1052 /* First fragment, or not fragmented. Dissect what we have here. */
1054 /* Get a tvbuff for the payload. */
1055 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1058 * If this is the first fragment, but not the only fragment,
1059 * tell the next protocol that.
1061 if (iph->ip_off & IP_MF)
1062 pinfo->fragmented = TRUE;
1064 pinfo->fragmented = FALSE;
1068 if (next_tvb == NULL) {
1069 /* Just show this as a fragment. */
1070 if (check_col(pinfo->cinfo, COL_INFO)) {
1071 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1072 ipprotostr(iph->ip_p), iph->ip_p, (iph->ip_off & IP_OFFSET) * 8);
1074 if( ipfd_head && ipfd_head->reassembled_in != pinfo->fd->num ){
1075 if (check_col(pinfo->cinfo, COL_INFO)) {
1076 col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]",
1077 ipfd_head->reassembled_in);
1081 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
1083 pinfo->fragmented = save_fragmented;
1087 /* Hand off to the next protocol.
1089 XXX - setting the columns only after trying various dissectors means
1090 that if one of those dissectors throws an exception, the frame won't
1091 even be labelled as an IP frame; ideally, if a frame being dissected
1092 throws an exception, it'll be labelled as a mangled frame of the
1093 type in question. */
1094 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
1095 /* Unknown protocol */
1096 if (update_col_info) {
1097 if (check_col(pinfo->cinfo, COL_INFO))
1098 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
1100 call_dissector(data_handle,next_tvb, pinfo, tree);
1102 pinfo->fragmented = save_fragmented;
1105 tap_queue_packet(ip_tap, pinfo, iph);
1109 #define ICMP_MIP_EXTENSION_PAD 0
1110 #define ICMP_MIP_MOB_AGENT_ADV 16
1111 #define ICMP_MIP_PREFIX_LENGTHS 19
1112 #define ICMP_MIP_CHALLENGE 24
1114 static value_string mip_extensions[] = {
1115 { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
1116 { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1118 { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
1119 { ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
1124 * Dissect the mobile ip advertisement extensions.
1127 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1133 proto_tree *mip_tree=NULL;
1134 proto_tree *flags_tree=NULL;
1138 /* Not much to do if we're not parsing everything */
1141 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1143 type = tvb_get_guint8(tvb, offset + 0);
1145 length = tvb_get_guint8(tvb, offset + 1);
1149 ti = proto_tree_add_text(tree, tvb, offset,
1150 type?(length + 2):1,
1152 val_to_str(type, mip_extensions,
1154 mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1158 case ICMP_MIP_EXTENSION_PAD:
1159 /* One byte padding extension */
1160 /* Add our fields */
1162 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1166 case ICMP_MIP_MOB_AGENT_ADV:
1167 /* Mobility Agent Advertisement Extension (RFC 2002)*/
1168 /* Add our fields */
1170 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1174 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1177 /* sequence number */
1178 proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset,
1181 /* Registration Lifetime */
1182 proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset,
1186 flags = tvb_get_guint8(tvb, offset);
1187 ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1189 flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1190 proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1191 proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1192 proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1193 proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1194 proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1195 proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1196 proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1197 proto_tree_add_boolean(flags_tree, hf_icmp_mip_res, tvb, offset, 1, flags);
1201 proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset,
1206 numCOAs = (length - 6) / 4;
1207 for (i=0; i<numCOAs; i++) {
1208 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset,
1213 case ICMP_MIP_PREFIX_LENGTHS:
1214 /* Prefix-Lengths Extension (RFC 2002)*/
1215 /* Add our fields */
1217 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1221 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1225 /* prefix lengths */
1226 for(i=0; i<length; i++) {
1227 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1232 case ICMP_MIP_CHALLENGE:
1233 /* Challenge Extension (RFC 3012)*/
1235 proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1239 proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1243 proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset,
1249 g_warning("Unknown type(%u)! I hope the length is right (%u)",
1251 offset += length + 2;
1256 } /* dissect_mip_extensions */
1258 static const gchar *unreach_str[] = {"Network unreachable",
1260 "Protocol unreachable",
1262 "Fragmentation needed",
1263 "Source route failed",
1264 "Destination network unknown",
1265 "Destination host unknown",
1266 "Source host isolated",
1267 "Network administratively prohibited",
1268 "Host administratively prohibited",
1269 "Network unreachable for TOS",
1270 "Host unreachable for TOS",
1271 "Communication administratively filtered",
1272 "Host precedence violation",
1273 "Precedence cutoff in effect"};
1275 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1277 static const gchar *redir_str[] = {"Redirect for network",
1278 "Redirect for host",
1279 "Redirect for TOS and network",
1280 "Redirect for TOS and host"};
1282 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1284 static const gchar *ttl_str[] = {"Time to live exceeded in transit",
1285 "Fragment reassembly time exceeded"};
1287 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1289 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1291 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1294 * RFC 792 for basic ICMP.
1295 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1296 * RFC 1256 for router discovery messages.
1297 * RFC 2002 and 3012 for Mobile IP stuff.
1300 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1302 proto_tree *icmp_tree;
1306 guint length, reported_length;
1307 guint16 cksum, computed_cksum;
1308 gchar type_str[64], code_str[64] = "";
1309 guint8 num_addrs = 0;
1310 guint8 addr_entry_size = 0;
1312 gboolean save_in_error_pkt;
1315 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1316 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1317 if (check_col(pinfo->cinfo, COL_INFO))
1318 col_clear(pinfo->cinfo, COL_INFO);
1320 /* To do: check for runts, errs, etc. */
1321 icmp_type = tvb_get_guint8(tvb, 0);
1322 icmp_code = tvb_get_guint8(tvb, 1);
1323 cksum = tvb_get_ntohs(tvb, 2);
1325 switch (icmp_type) {
1326 case ICMP_ECHOREPLY:
1327 strcpy(type_str, "Echo (ping) reply");
1330 strcpy(type_str, "Destination unreachable");
1331 if (icmp_code < N_UNREACH) {
1332 sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1334 strcpy(code_str, "(Unknown - error?)");
1337 case ICMP_SOURCEQUENCH:
1338 strcpy(type_str, "Source quench (flow control)");
1341 strcpy(type_str, "Redirect");
1342 if (icmp_code < N_REDIRECT) {
1343 sprintf(code_str, "(%s)", redir_str[icmp_code]);
1345 strcpy(code_str, "(Unknown - error?)");
1349 strcpy(type_str, "Echo (ping) request");
1351 case ICMP_RTRADVERT:
1352 switch (icmp_code) {
1353 case 16: /* Mobile-Ip */
1354 strcpy(type_str, "Mobile IP Advertisement");
1357 strcpy(type_str, "Router advertisement");
1359 } /* switch icmp_code */
1361 case ICMP_RTRSOLICIT:
1362 strcpy(type_str, "Router solicitation");
1365 strcpy(type_str, "Time-to-live exceeded");
1366 if (icmp_code < N_TIMXCEED) {
1367 sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1369 strcpy(code_str, "(Unknown - error?)");
1372 case ICMP_PARAMPROB:
1373 strcpy(type_str, "Parameter problem");
1374 if (icmp_code < N_PARAMPROB) {
1375 sprintf(code_str, "(%s)", par_str[icmp_code]);
1377 strcpy(code_str, "(Unknown - error?)");
1381 strcpy(type_str, "Timestamp request");
1383 case ICMP_TSTAMPREPLY:
1384 strcpy(type_str, "Timestamp reply");
1387 strcpy(type_str, "Information request");
1389 case ICMP_IREQREPLY:
1390 strcpy(type_str, "Information reply");
1393 strcpy(type_str, "Address mask request");
1395 case ICMP_MASKREPLY:
1396 strcpy(type_str, "Address mask reply");
1399 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1403 if (check_col(pinfo->cinfo, COL_INFO))
1404 col_add_str(pinfo->cinfo, COL_INFO, type_str);
1407 length = tvb_length(tvb);
1408 reported_length = tvb_reported_length(tvb);
1409 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1410 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1411 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1414 icmp_type, type_str);
1415 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1418 icmp_code, code_str);
1420 if (!pinfo->fragmented && length >= reported_length) {
1421 /* The packet isn't part of a fragmented datagram and isn't
1422 truncated, so we can checksum it. */
1424 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1426 if (computed_cksum == 0) {
1427 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1429 "Checksum: 0x%04x (correct)", cksum);
1431 proto_tree_add_boolean_hidden(icmp_tree, hf_icmp_checksum_bad,
1433 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1435 "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1436 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1439 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1442 /* Decode the second 4 bytes of the packet. */
1443 switch (icmp_type) {
1444 case ICMP_ECHOREPLY:
1447 case ICMP_TSTAMPREPLY:
1449 case ICMP_IREQREPLY:
1451 case ICMP_MASKREPLY:
1452 proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, FALSE);
1453 proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2, FALSE);
1457 switch (icmp_code) {
1458 case ICMP_FRAG_NEEDED:
1459 proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6, 2, FALSE);
1464 case ICMP_RTRADVERT:
1465 num_addrs = tvb_get_guint8(tvb, 4);
1466 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1468 addr_entry_size = tvb_get_guint8(tvb, 5);
1469 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1471 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1472 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1475 case ICMP_PARAMPROB:
1476 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1477 tvb_get_guint8(tvb, 4));
1481 proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4, FALSE);
1485 /* Decode the additional information in the packet. */
1486 switch (icmp_type) {
1489 case ICMP_PARAMPROB:
1490 case ICMP_SOURCEQUENCH:
1492 /* Save the current value of the "we're inside an error packet"
1493 flag, and set that flag; subdissectors may treat packets
1494 that are the payload of error packets differently from
1496 save_in_error_pkt = pinfo->in_error_pkt;
1497 pinfo->in_error_pkt = TRUE;
1499 /* Decode the IP header and first 64 bits of data from the
1500 original datagram. */
1501 next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1502 call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1504 /* Restore the "we're inside an error packet" flag. */
1505 pinfo->in_error_pkt = save_in_error_pkt;
1508 case ICMP_ECHOREPLY:
1510 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1514 case ICMP_RTRADVERT:
1515 if (addr_entry_size == 2) {
1516 for (i = 0; i < num_addrs; i++) {
1517 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1518 "Router address: %s",
1519 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1520 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1521 "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1523 if (icmp_code == 16) {
1525 dissect_mip_extensions(tvb, 8 + i*8, icmp_tree);
1528 call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1533 case ICMP_TSTAMPREPLY:
1534 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1535 tvb_get_ntohl(tvb, 8));
1536 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1537 tvb_get_ntohl(tvb, 12));
1538 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1539 tvb_get_ntohl(tvb, 16));
1543 case ICMP_MASKREPLY:
1544 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1545 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1552 proto_register_ip(void)
1554 static hf_register_info hf[] = {
1557 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1561 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1565 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1568 { &hf_ip_dsfield_dscp,
1569 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1570 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1573 { &hf_ip_dsfield_ect,
1574 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1578 { &hf_ip_dsfield_ce,
1579 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1584 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1587 { &hf_ip_tos_precedence,
1588 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1593 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1597 { &hf_ip_tos_throughput,
1598 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1602 { &hf_ip_tos_reliability,
1603 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1608 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1613 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1617 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1621 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1625 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1629 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1633 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1637 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1641 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1644 { &hf_ip_frag_offset,
1645 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1649 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1653 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1657 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1660 { &hf_ip_checksum_bad,
1661 { "Bad Header checksum", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1664 { &hf_ip_fragment_overlap,
1665 { "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1666 "Fragment overlaps with other fragments", HFILL }},
1668 { &hf_ip_fragment_overlap_conflict,
1669 { "Conflicting data in fragment overlap", "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1670 "Overlapping fragments contained conflicting data", HFILL }},
1672 { &hf_ip_fragment_multiple_tails,
1673 { "Multiple tail fragments found", "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1674 "Several tails were found when defragmenting the packet", HFILL }},
1676 { &hf_ip_fragment_too_long_fragment,
1677 { "Fragment too long", "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1678 "Fragment contained data past end of packet", HFILL }},
1680 { &hf_ip_fragment_error,
1681 { "Defragmentation error", "ip.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1682 "Defragmentation error due to illegal fragments", HFILL }},
1685 { "IP Fragment", "ip.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1686 "IP Fragment", HFILL }},
1689 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1690 "IP Fragments", HFILL }},
1692 { &hf_ip_reassembled_in,
1693 { "Reassembled IP in frame", "ip.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1694 "This IP packet is reassembled in this frame", HFILL }}
1696 static gint *ett[] = {
1703 &ett_ip_option_route,
1704 &ett_ip_option_timestamp,
1708 module_t *ip_module;
1710 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1711 proto_register_field_array(proto_ip, hf, array_length(hf));
1712 proto_register_subtree_array(ett, array_length(ett));
1714 /* subdissector code */
1715 ip_dissector_table = register_dissector_table("ip.proto",
1716 "IP protocol", FT_UINT8, BASE_DEC);
1718 /* Register configuration options */
1719 ip_module = prefs_register_protocol(proto_ip, NULL);
1720 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1721 "Decode IPv4 TOS field as DiffServ field",
1722 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1724 prefs_register_bool_preference(ip_module, "defragment",
1725 "Reassemble fragmented IP datagrams",
1726 "Whether fragmented IP datagrams should be reassembled",
1728 prefs_register_bool_preference(ip_module, "summary_in_tree",
1729 "Show IP summary in protocol tree",
1730 "Whether the IP summary line should be shown in the protocol tree",
1731 &ip_summary_in_tree);
1733 register_dissector("ip", dissect_ip, proto_ip);
1734 register_init_routine(ip_defragment_init);
1735 ip_tap=register_tap("ip");
1739 proto_reg_handoff_ip(void)
1741 dissector_handle_t ip_handle;
1743 data_handle = find_dissector("data");
1744 ip_handle = find_dissector("ip");
1745 dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
1746 dissector_add("ppp.protocol", PPP_IP, ip_handle);
1747 dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
1748 dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
1749 dissector_add("gre.proto", GRE_WCCP, ip_handle);
1750 dissector_add("llc.dsap", SAP_IP, ip_handle);
1751 dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
1752 dissector_add("null.type", BSD_AF_INET, ip_handle);
1753 dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
1754 dissector_add("fr.ietf", NLPID_IP, ip_handle);
1755 dissector_add("x.25.spi", NLPID_IP, ip_handle);
1756 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1051, ip_handle);
1757 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1201, ip_handle);
1761 proto_register_icmp(void)
1763 static hf_register_info hf[] = {
1766 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1770 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1773 { &hf_icmp_checksum,
1774 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1777 { &hf_icmp_checksum_bad,
1778 { "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1782 {"Identifier", "icmp.ident", FT_UINT16, BASE_HEX, NULL, 0x0,
1786 {"Sequence number", "icmp.seq", FT_UINT16, BASE_HEX, NULL, 0x0,
1790 {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL, 0x0,
1793 { &hf_icmp_redir_gw,
1794 {"Gateway address", "icmp.redir_gw", FT_IPv4, BASE_NONE, NULL, 0x0,
1797 { &hf_icmp_mip_type,
1798 { "Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
1799 VALS(mip_extensions), 0x0,"", HFILL}},
1801 { &hf_icmp_mip_length,
1802 { "Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL, 0x0,
1805 { &hf_icmp_mip_prefix_length,
1806 { "Prefix Length", "icmp.mip.prefixlength", FT_UINT8, BASE_DEC, NULL, 0x0,
1810 { "Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC, NULL, 0x0,
1813 { &hf_icmp_mip_life,
1814 { "Registration Lifetime", "icmp.mip.life", FT_UINT16, BASE_DEC, NULL, 0x0,
1817 { &hf_icmp_mip_flags,
1818 { "Flags", "icmp.mip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1822 { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
1823 "Registration with this FA is required", HFILL }},
1826 { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
1827 "This FA will not accept requests at this time", HFILL }},
1830 { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
1831 "Home Agent Services Offered", HFILL }},
1834 { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
1835 "Foreign Agent Services Offered", HFILL }},
1838 { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
1839 "Minimal encapsulation tunneled datagram support", HFILL }},
1842 { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
1843 "GRE encapsulated tunneled datagram support", HFILL }},
1846 { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
1847 "Van Jacobson Header Compression Support", HFILL }},
1850 { "Reserved", "icmp.mip.res", FT_BOOLEAN, 8, NULL, 1,
1851 "Reserved", HFILL }},
1853 { &hf_icmp_mip_reserved,
1854 { "Reserved", "icmp.mip.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
1858 { "Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE, NULL, 0x0,
1861 { &hf_icmp_mip_challenge,
1862 { "Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE, NULL, 0x0,
1865 static gint *ett[] = {
1871 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
1873 proto_register_field_array(proto_icmp, hf, array_length(hf));
1874 proto_register_subtree_array(ett, array_length(ett));
1878 proto_reg_handoff_icmp(void)
1880 dissector_handle_t icmp_handle;
1883 * Get handle for the IP dissector.
1885 ip_handle = find_dissector("ip");
1887 icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
1888 dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);