2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.127 2001/03/15 09:11:00 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
42 #ifdef NEED_SNPRINTF_H
43 # include "snprintf.h"
54 #include "packet-ip.h"
55 #include "packet-ipsec.h"
59 static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
60 static void dissect_igmp(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 static int proto_ip = -1;
66 static int hf_ip_version = -1;
67 static int hf_ip_hdr_len = -1;
68 static int hf_ip_dsfield = -1;
69 static int hf_ip_dsfield_dscp = -1;
70 static int hf_ip_dsfield_ect = -1;
71 static int hf_ip_dsfield_ce = -1;
72 static int hf_ip_tos = -1;
73 static int hf_ip_tos_precedence = -1;
74 static int hf_ip_tos_delay = -1;
75 static int hf_ip_tos_throughput = -1;
76 static int hf_ip_tos_reliability = -1;
77 static int hf_ip_tos_cost = -1;
78 static int hf_ip_len = -1;
79 static int hf_ip_id = -1;
80 static int hf_ip_dst = -1;
81 static int hf_ip_src = -1;
82 static int hf_ip_addr = -1;
83 static int hf_ip_flags = -1;
84 static int hf_ip_flags_df = -1;
85 static int hf_ip_flags_mf = -1;
86 static int hf_ip_frag_offset = -1;
87 static int hf_ip_ttl = -1;
88 static int hf_ip_proto = -1;
89 static int hf_ip_checksum = -1;
90 static int hf_ip_checksum_bad = -1;
92 static gint ett_ip = -1;
93 static gint ett_ip_dsfield = -1;
94 static gint ett_ip_tos = -1;
95 static gint ett_ip_off = -1;
96 static gint ett_ip_options = -1;
97 static gint ett_ip_option_sec = -1;
98 static gint ett_ip_option_route = -1;
99 static gint ett_ip_option_timestamp = -1;
101 /* Used by IPv6 as well, so not static */
102 dissector_table_t ip_dissector_table;
104 static int proto_igmp = -1;
105 static int hf_igmp_version = -1;
106 static int hf_igmp_type = -1;
107 static int hf_igmp_unused = -1;
108 static int hf_igmp_checksum = -1;
109 static int hf_igmp_group = -1;
111 static gint ett_igmp = -1;
113 static int proto_icmp = -1;
114 static int hf_icmp_type = -1;
115 static int hf_icmp_code = -1;
116 static int hf_icmp_checksum = -1;
117 static int hf_icmp_checksum_bad = -1;
119 static gint ett_icmp = -1;
121 /* ICMP definitions */
123 #define ICMP_ECHOREPLY 0
124 #define ICMP_UNREACH 3
125 #define ICMP_SOURCEQUENCH 4
126 #define ICMP_REDIRECT 5
128 #define ICMP_RTRADVERT 9
129 #define ICMP_RTRSOLICIT 10
130 #define ICMP_TIMXCEED 11
131 #define ICMP_PARAMPROB 12
132 #define ICMP_TSTAMP 13
133 #define ICMP_TSTAMPREPLY 14
135 #define ICMP_IREQREPLY 16
136 #define ICMP_MASKREQ 17
137 #define ICMP_MASKREPLY 18
139 /* ICMP UNREACHABLE */
141 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
142 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
143 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
144 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
145 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
146 #define ICMP_SR_FAILED 5 /* Source Route failed */
147 #define ICMP_NET_UNKNOWN 6
148 #define ICMP_HOST_UNKNOWN 7
149 #define ICMP_HOST_ISOLATED 8
150 #define ICMP_NET_ANO 9
151 #define ICMP_HOST_ANO 10
152 #define ICMP_NET_UNR_TOS 11
153 #define ICMP_HOST_UNR_TOS 12
154 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
155 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
156 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
159 /* IGMP structs and definitions */
160 typedef struct _e_igmp {
161 guint8 igmp_v_t; /* combines igmp_v and igmp_t */
167 #define IGMP_M_QRY 0x01
168 #define IGMP_V1_M_RPT 0x02
169 #define IGMP_V2_LV_GRP 0x07
170 #define IGMP_DVMRP 0x03
171 #define IGMP_PIM 0x04
172 #define IGMP_V2_M_RPT 0x06
173 #define IGMP_MTRC_RESP 0x1e
174 #define IGMP_MTRC 0x1f
176 /* IP structs and definitions */
180 guint8 ip_v_hl; /* combines ip_v and ip_hl */
192 /* Offsets of fields within an IP header. */
204 /* Minimum IP header length. */
205 #define IPH_MIN_LEN 20
208 #define IP_CE 0x8000 /* Flag: "Congestion" */
209 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
210 #define IP_MF 0x2000 /* Flag: "More Fragments" */
211 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
213 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
214 #define IPDSFIELD_DSCP_MASK 0xFC
215 #define IPDSFIELD_ECN_MASK 0x03
216 #define IPDSFIELD_DSCP_SHIFT 2
217 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
218 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
219 #define IPDSFIELD_DSCP_DEFAULT 0x00
220 #define IPDSFIELD_DSCP_CS1 0x08
221 #define IPDSFIELD_DSCP_CS2 0x10
222 #define IPDSFIELD_DSCP_CS3 0x18
223 #define IPDSFIELD_DSCP_CS4 0x20
224 #define IPDSFIELD_DSCP_CS5 0x28
225 #define IPDSFIELD_DSCP_CS6 0x30
226 #define IPDSFIELD_DSCP_CS7 0x38
227 #define IPDSFIELD_DSCP_AF11 0x0A
228 #define IPDSFIELD_DSCP_AF12 0x0C
229 #define IPDSFIELD_DSCP_AF13 0x0E
230 #define IPDSFIELD_DSCP_AF21 0x12
231 #define IPDSFIELD_DSCP_AF22 0x14
232 #define IPDSFIELD_DSCP_AF23 0x16
233 #define IPDSFIELD_DSCP_AF31 0x1A
234 #define IPDSFIELD_DSCP_AF32 0x1C
235 #define IPDSFIELD_DSCP_AF33 0x1E
236 #define IPDSFIELD_DSCP_AF41 0x22
237 #define IPDSFIELD_DSCP_AF42 0x24
238 #define IPDSFIELD_DSCP_AF43 0x26
239 #define IPDSFIELD_DSCP_EF 0x2E
240 #define IPDSFIELD_ECT_MASK 0x02
241 #define IPDSFIELD_CE_MASK 0x01
243 /* IP TOS, superseded by the DS Field, RFC 2474. */
244 #define IPTOS_TOS_MASK 0x1E
245 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
246 #define IPTOS_NONE 0x00
247 #define IPTOS_LOWCOST 0x02
248 #define IPTOS_RELIABILITY 0x04
249 #define IPTOS_THROUGHPUT 0x08
250 #define IPTOS_LOWDELAY 0x10
251 #define IPTOS_SECURITY 0x1E
253 #define IPTOS_PREC_MASK 0xE0
254 #define IPTOS_PREC_SHIFT 5
255 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
256 #define IPTOS_PREC_NETCONTROL 7
257 #define IPTOS_PREC_INTERNETCONTROL 6
258 #define IPTOS_PREC_CRITIC_ECP 5
259 #define IPTOS_PREC_FLASHOVERRIDE 4
260 #define IPTOS_PREC_FLASH 3
261 #define IPTOS_PREC_IMMEDIATE 2
262 #define IPTOS_PREC_PRIORITY 1
263 #define IPTOS_PREC_ROUTINE 0
266 #define IPOPT_COPY 0x80
268 #define IPOPT_CONTROL 0x00
269 #define IPOPT_RESERVED1 0x20
270 #define IPOPT_MEASUREMENT 0x40
271 #define IPOPT_RESERVED2 0x60
273 #define IPOPT_END (0 |IPOPT_CONTROL)
274 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
275 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
276 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
277 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
278 #define IPOPT_RR (7 |IPOPT_CONTROL)
279 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
280 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
281 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
283 /* IP option lengths */
284 #define IPOLEN_SEC 11
285 #define IPOLEN_LSRR_MIN 3
286 #define IPOLEN_TIMESTAMP_MIN 5
287 #define IPOLEN_RR_MIN 3
289 #define IPOLEN_SSRR_MIN 3
292 #define IPSEC_UNCLASSIFIED 0x0000
293 #define IPSEC_CONFIDENTIAL 0xF135
294 #define IPSEC_EFTO 0x789A
295 #define IPSEC_MMMM 0xBC4D
296 #define IPSEC_RESTRICTED 0xAF13
297 #define IPSEC_SECRET 0xD788
298 #define IPSEC_TOPSECRET 0x6BC5
299 #define IPSEC_RESERVED1 0x35E2
300 #define IPSEC_RESERVED2 0x9AF1
301 #define IPSEC_RESERVED3 0x4D78
302 #define IPSEC_RESERVED4 0x24BD
303 #define IPSEC_RESERVED5 0x135E
304 #define IPSEC_RESERVED6 0x89AF
305 #define IPSEC_RESERVED7 0xC4D6
306 #define IPSEC_RESERVED8 0xE26B
308 #define IPOPT_TS_TSONLY 0 /* timestamps only */
309 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
310 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
314 capture_ip(const u_char *pd, int offset, packet_counts *ld) {
315 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
319 switch (pd[offset + 9]) {
347 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
348 guint optlen, frame_data *fd, proto_tree *opt_tree)
350 proto_tree *field_tree = NULL;
353 static const value_string secl_vals[] = {
354 {IPSEC_UNCLASSIFIED, "Unclassified"},
355 {IPSEC_CONFIDENTIAL, "Confidential"},
356 {IPSEC_EFTO, "EFTO" },
357 {IPSEC_MMMM, "MMMM" },
358 {IPSEC_RESTRICTED, "Restricted" },
359 {IPSEC_SECRET, "Secret" },
360 {IPSEC_TOPSECRET, "Top secret" },
361 {IPSEC_RESERVED1, "Reserved" },
362 {IPSEC_RESERVED2, "Reserved" },
363 {IPSEC_RESERVED3, "Reserved" },
364 {IPSEC_RESERVED4, "Reserved" },
365 {IPSEC_RESERVED5, "Reserved" },
366 {IPSEC_RESERVED6, "Reserved" },
367 {IPSEC_RESERVED7, "Reserved" },
368 {IPSEC_RESERVED8, "Reserved" },
371 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
372 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
375 val = tvb_get_ntohs(tvb, offset);
376 proto_tree_add_text(field_tree, tvb, offset, 2,
377 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
380 val = tvb_get_ntohs(tvb, offset);
381 proto_tree_add_text(field_tree, tvb, offset, 2,
382 "Compartments: %u", val);
385 proto_tree_add_text(field_tree, tvb, offset, 2,
386 "Handling restrictions: %c%c",
387 tvb_get_guint8(tvb, offset),
388 tvb_get_guint8(tvb, offset + 1));
391 proto_tree_add_text(field_tree, tvb, offset, 3,
392 "Transmission control code: %c%c%c",
393 tvb_get_guint8(tvb, offset),
394 tvb_get_guint8(tvb, offset + 1),
395 tvb_get_guint8(tvb, offset + 2));
399 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
400 guint optlen, frame_data *fd, proto_tree *opt_tree)
402 proto_tree *field_tree = NULL;
408 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
410 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
412 optoffset += 2; /* skip past type and length */
413 optlen -= 2; /* subtract size of type and length */
415 ptr = tvb_get_guint8(tvb, offset + optoffset);
416 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
417 "Pointer: %d%s", ptr,
418 ((ptr < 4) ? " (points before first address)" :
419 ((ptr & 3) ? " (points to middle of address)" : "")));
422 ptr--; /* ptr is 1-origin */
426 proto_tree_add_text(field_tree, tvb, offset, optlen,
427 "(suboption would go past end of option)");
431 /* Avoids alignment problems on many architectures. */
432 tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
434 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
436 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
437 ((optoffset == ptr) ? " <- (current)" : ""));
444 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
445 guint optlen, frame_data *fd, proto_tree *opt_tree)
447 proto_tree_add_text(opt_tree, tvb, offset, optlen,
448 "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
453 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
454 int offset, guint optlen, frame_data *fd, proto_tree *opt_tree)
456 proto_tree *field_tree = NULL;
461 static const value_string flag_vals[] = {
462 {IPOPT_TS_TSONLY, "Time stamps only" },
463 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
464 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
469 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
470 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
472 optoffset += 2; /* skip past type and length */
473 optlen -= 2; /* subtract size of type and length */
475 ptr = tvb_get_guint8(tvb, offset + optoffset);
476 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
477 "Pointer: %d%s", ptr,
478 ((ptr < 5) ? " (points before first address)" :
479 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
482 ptr--; /* ptr is 1-origin */
484 flg = tvb_get_guint8(tvb, offset + optoffset);
485 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
486 "Overflow: %u", flg >> 4);
488 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
489 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
494 if (flg == IPOPT_TS_TSANDADDR) {
496 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
497 "(suboption would go past end of option)");
500 tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
501 ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
503 proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
504 "Address = %s, time stamp = %u",
505 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
510 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
511 "(suboption would go past end of option)");
514 ts = tvb_get_ntohl(tvb, offset + optoffset);
516 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
517 "Time stamp = %u", ts);
524 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
525 guint optlen, frame_data *fd, proto_tree *opt_tree)
527 /* Router-Alert, as defined by RFC2113 */
528 int opt = tvb_get_ntohs(tvb, offset + 2);
529 static const value_string ra_opts[] = {
530 {0, "Every router examines packet"},
534 proto_tree_add_text(opt_tree, tvb, offset, optlen,
535 "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
539 static const ip_tcp_opt ipopts[] = {
562 dissect_ipopt_security
566 "Strict source route",
567 &ett_ip_option_route,
574 "Loose source route",
575 &ett_ip_option_route,
583 &ett_ip_option_route,
599 &ett_ip_option_timestamp,
601 IPOLEN_TIMESTAMP_MIN,
602 dissect_ipopt_timestamp
614 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
616 /* Dissect the IP or TCP options in a packet. */
618 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
619 const ip_tcp_opt *opttab, int nopts, int eol,
620 frame_data *fd, proto_tree *opt_tree)
623 const ip_tcp_opt *optp;
624 opt_len_type len_type;
627 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
628 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
629 int, guint, frame_data *, proto_tree *);
633 opt = tvb_get_guint8(tvb, offset);
634 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
635 if (optp->optcode == opt)
638 if (optp == &opttab[nopts]) {
639 /* We assume that the only NO_LENGTH options are EOL and NOP options,
640 so that we can treat unknown options as VARIABLE_LENGTH with a
641 minimum of 2, and at least be able to move on to the next option
642 by using the length in the option. */
643 optp = NULL; /* indicate that we don't know this option */
644 len_type = VARIABLE_LENGTH;
646 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
650 len_type = optp->len_type;
651 optlen = optp->optlen;
653 dissect = optp->dissect;
655 --length; /* account for type byte */
656 if (len_type != NO_LENGTH) {
657 /* Option has a length. Is it in the packet? */
659 /* Bogus - packet must at least include option code byte and
661 proto_tree_add_text(opt_tree, tvb, offset, 1,
662 "%s (length byte past end of options)", name);
665 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
666 --length; /* account for length byte */
668 /* Bogus - option length is too short to include option code and
670 proto_tree_add_text(opt_tree, tvb, offset, 2,
671 "%s (with too-short option length = %u byte%s)", name,
672 len, plurality(len, "", "s"));
674 } else if (len - 2 > length) {
675 /* Bogus - option goes past the end of the header. */
676 proto_tree_add_text(opt_tree, tvb, offset, length,
677 "%s (option length = %u byte%s says option goes past end of options)",
678 name, len, plurality(len, "", "s"));
680 } else if (len_type == FIXED_LENGTH && len != optlen) {
681 /* Bogus - option length isn't what it's supposed to be for this
683 proto_tree_add_text(opt_tree, tvb, offset, len,
684 "%s (with option length = %u byte%s; should be %u)", name,
685 len, plurality(len, "", "s"), optlen);
687 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
688 /* Bogus - option length is less than what it's supposed to be for
690 proto_tree_add_text(opt_tree, tvb, offset, len,
691 "%s (with option length = %u byte%s; should be >= %u)", name,
692 len, plurality(len, "", "s"), optlen);
696 proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
697 name, len, plurality(len, "", "s"));
699 if (dissect != NULL) {
700 /* Option has a dissector. */
701 (*dissect)(optp, tvb, offset, len, fd, opt_tree);
703 /* Option has no data, hence no dissector. */
704 proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
707 len -= 2; /* subtract size of type and length */
712 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
720 static const value_string dscp_vals[] = {
721 { IPDSFIELD_DSCP_DEFAULT, "Default" },
722 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
723 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
724 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
725 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
726 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
727 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
728 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
729 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
730 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
731 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
732 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
733 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
734 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
735 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
736 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
737 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
738 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
739 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
740 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
741 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
744 static const value_string precedence_vals[] = {
745 { IPTOS_PREC_ROUTINE, "routine" },
746 { IPTOS_PREC_PRIORITY, "priority" },
747 { IPTOS_PREC_IMMEDIATE, "immediate" },
748 { IPTOS_PREC_FLASH, "flash" },
749 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
750 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
751 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
752 { IPTOS_PREC_NETCONTROL, "network control" },
755 static const value_string iptos_vals[] = {
756 { IPTOS_NONE, "None" },
757 { IPTOS_LOWCOST, "Minimize cost" },
758 { IPTOS_RELIABILITY, "Maximize reliability" },
759 { IPTOS_THROUGHPUT, "Maximize throughput" },
760 { IPTOS_LOWDELAY, "Minimize delay" },
761 { IPTOS_SECURITY, "Maximize security" },
765 static const true_false_string tos_set_low = {
770 static const true_false_string tos_set_high = {
775 static const true_false_string flags_set_truth = {
780 static guint16 ip_checksum(const guint8 *ptr, int len)
784 cksum_vec[0].ptr = ptr;
785 cksum_vec[0].len = len;
786 return in_cksum(&cksum_vec[0], 1);
790 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
793 proto_tree *ip_tree, *field_tree;
796 guint hlen, optlen, len, payload_len, reported_payload_len, padding;
802 if (check_col(pinfo->fd, COL_PROTOCOL))
803 col_set_str(pinfo->fd, COL_PROTOCOL, "IP");
804 if (check_col(pinfo->fd, COL_INFO))
805 col_clear(pinfo->fd, COL_INFO);
807 /* Avoids alignment problems on many architectures. */
808 tvb_memcpy(tvb, (guint8 *)&iph, offset, sizeof(e_ip));
809 iph.ip_len = ntohs(iph.ip_len);
810 iph.ip_id = ntohs(iph.ip_id);
811 iph.ip_off = ntohs(iph.ip_off);
812 iph.ip_sum = ntohs(iph.ip_sum);
814 /* Length of payload handed to us. */
815 reported_payload_len = tvb_reported_length(tvb);
816 payload_len = tvb_length(tvb);
818 /* Length of IP datagram. */
821 if (len < reported_payload_len) {
822 /* Adjust the length of this tvbuff to include only the IP datagram.
823 Our caller may use that to determine how much of its packet
825 tvb_set_reported_length(tvb, len);
827 /* Shrink the total payload by the amount of padding. */
828 padding = reported_payload_len - len;
829 if (pinfo->len >= padding)
830 pinfo->len -= padding;
832 /* Shrink the captured payload by the amount of padding in the
833 captured payload (which may be less than the amount of padding,
834 as the padding may not have been captured). */
835 if (len < payload_len) {
836 padding = payload_len - len;
837 if (pinfo->captured_len >= padding)
838 pinfo->captured_len -= padding;
842 /* XXX - check to make sure this is at least IPH_MIN_LEN. */
843 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
846 ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
847 ip_tree = proto_item_add_subtree(ti, ett_ip);
849 proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1, hi_nibble(iph.ip_v_hl));
850 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
851 "Header length: %u bytes", hlen);
853 if (g_ip_dscp_actif) {
854 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph.ip_tos,
855 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph.ip_tos,
856 IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
857 "Unknown DSCP"),IPDSFIELD_ECN(iph.ip_tos));
859 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
860 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph.ip_tos);
861 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph.ip_tos);
862 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph.ip_tos);
864 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph.ip_tos,
865 "Type of service: 0x%02x (%s)", iph.ip_tos,
866 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
868 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
869 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph.ip_tos);
870 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph.ip_tos);
871 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph.ip_tos);
872 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph.ip_tos);
873 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph.ip_tos);
875 proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph.ip_len);
876 proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph.ip_id);
878 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
879 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
880 field_tree = proto_item_add_subtree(tf, ett_ip_off);
881 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
882 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
884 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
885 (iph.ip_off & IP_OFFSET)*8);
886 proto_tree_add_uint(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, iph.ip_ttl);
887 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph.ip_p,
888 "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
890 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
892 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
893 "Header checksum: 0x%04x (correct)", iph.ip_sum);
896 proto_tree_add_item_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
897 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
898 "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph.ip_sum,
899 in_cksum_shouldbe(iph.ip_sum, ipsum));
902 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, iph.ip_src);
903 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, iph.ip_dst);
904 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, iph.ip_src);
905 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, iph.ip_dst);
907 /* Decode IP options, if any. */
908 if (hlen > sizeof (e_ip)) {
909 /* There's more than just the fixed-length header. Decode the
911 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
912 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
913 "Options: (%u bytes)", optlen);
914 field_tree = proto_item_add_subtree(tf, ett_ip_options);
915 dissect_ip_tcp_options(tvb, offset + 20, optlen,
916 ipopts, N_IP_OPTS, IPOPT_END, pinfo->fd, field_tree);
920 pinfo->ipproto = iph.ip_p;
921 pinfo->iplen = iph.ip_len;
922 pinfo->iphdrlen = lo_nibble(iph.ip_v_hl);
923 SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
924 SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
925 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
926 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
928 /* Skip over header + options */
931 if (iph.ip_off & IP_OFFSET) {
933 if (check_col(pinfo->fd, COL_INFO))
934 col_add_fstr(pinfo->fd, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
935 ipprotostr(iph.ip_p), iph.ip_p, (iph.ip_off & IP_OFFSET) * 8);
936 dissect_data(tvb, offset, pinfo, tree);
941 * If this is the first fragment, but not the only fragment,
942 * tell the next protocol that.
944 if (iph.ip_off & IP_MF)
945 pinfo->fragmented = TRUE;
947 pinfo->fragmented = FALSE;
949 /* Hand off to the next protocol.
951 XXX - setting the columns only after trying various dissectors means
952 that if one of those dissectors throws an exception, the frame won't
953 even be labelled as an IP frame; ideally, if a frame being dissected
954 throws an exception, it'll be labelled as a mangled frame of the
956 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
957 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
958 /* Unknown protocol */
959 if (check_col(pinfo->fd, COL_INFO))
960 col_add_fstr(pinfo->fd, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
961 dissect_data(next_tvb, 0, pinfo, tree);
966 static const gchar *unreach_str[] = {"Network unreachable",
968 "Protocol unreachable",
970 "Fragmentation needed",
971 "Source route failed",
972 "Destination network unknown",
973 "Destination host unknown",
974 "Source host isolated",
975 "Network administratively prohibited",
976 "Host administratively prohibited",
977 "Network unreachable for TOS",
978 "Host unreachable for TOS",
979 "Communication administratively filtered",
980 "Host precedence violation",
981 "Precedence cutoff in effect"};
983 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
985 static const gchar *redir_str[] = {"Redirect for network",
987 "Redirect for TOS and network",
988 "Redirect for TOS and host"};
990 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
992 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
993 "TTL equals 0 during reassembly"};
995 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
997 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
999 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1002 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1004 proto_tree *icmp_tree;
1008 guint length, reported_length;
1009 guint16 cksum, computed_cksum;
1010 gchar type_str[64], code_str[64] = "";
1011 guint8 num_addrs = 0;
1012 guint8 addr_entry_size = 0;
1015 if (check_col(pinfo->fd, COL_PROTOCOL))
1016 col_set_str(pinfo->fd, COL_PROTOCOL, "ICMP");
1017 if (check_col(pinfo->fd, COL_INFO))
1018 col_clear(pinfo->fd, COL_INFO);
1020 /* To do: check for runts, errs, etc. */
1021 icmp_type = tvb_get_guint8(tvb, 0);
1022 icmp_code = tvb_get_guint8(tvb, 1);
1023 cksum = tvb_get_ntohs(tvb, 2);
1025 switch (icmp_type) {
1026 case ICMP_ECHOREPLY:
1027 strcpy(type_str, "Echo (ping) reply");
1030 strcpy(type_str, "Destination unreachable");
1031 if (icmp_code < N_UNREACH) {
1032 sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1034 strcpy(code_str, "(Unknown - error?)");
1037 case ICMP_SOURCEQUENCH:
1038 strcpy(type_str, "Source quench (flow control)");
1041 strcpy(type_str, "Redirect");
1042 if (icmp_code < N_REDIRECT) {
1043 sprintf(code_str, "(%s)", redir_str[icmp_code]);
1045 strcpy(code_str, "(Unknown - error?)");
1049 strcpy(type_str, "Echo (ping) request");
1051 case ICMP_RTRADVERT:
1052 strcpy(type_str, "Router advertisement");
1054 case ICMP_RTRSOLICIT:
1055 strcpy(type_str, "Router solicitation");
1058 strcpy(type_str, "Time-to-live exceeded");
1059 if (icmp_code < N_TIMXCEED) {
1060 sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1062 strcpy(code_str, "(Unknown - error?)");
1065 case ICMP_PARAMPROB:
1066 strcpy(type_str, "Parameter problem");
1067 if (icmp_code < N_PARAMPROB) {
1068 sprintf(code_str, "(%s)", par_str[icmp_code]);
1070 strcpy(code_str, "(Unknown - error?)");
1074 strcpy(type_str, "Timestamp request");
1076 case ICMP_TSTAMPREPLY:
1077 strcpy(type_str, "Timestamp reply");
1080 strcpy(type_str, "Information request");
1082 case ICMP_IREQREPLY:
1083 strcpy(type_str, "Information reply");
1086 strcpy(type_str, "Address mask request");
1088 case ICMP_MASKREPLY:
1089 strcpy(type_str, "Address mask reply");
1092 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1095 if (check_col(pinfo->fd, COL_INFO))
1096 col_add_str(pinfo->fd, COL_INFO, type_str);
1099 length = tvb_length(tvb);
1100 reported_length = tvb_reported_length(tvb);
1101 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1102 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1103 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1106 icmp_type, type_str);
1107 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1110 icmp_code, code_str);
1112 if (!pinfo->fragmented && length >= reported_length) {
1113 /* The packet isn't part of a fragmented datagram and isn't
1114 truncated, so we can checksum it. */
1116 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1118 if (computed_cksum == 0) {
1119 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1121 "Checksum: 0x%04x (correct)", cksum);
1123 proto_tree_add_item_hidden(icmp_tree, hf_icmp_checksum_bad,
1125 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1127 "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1128 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1131 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1134 /* Decode the second 4 bytes of the packet. */
1135 switch (icmp_type) {
1136 case ICMP_ECHOREPLY:
1139 case ICMP_TSTAMPREPLY:
1141 case ICMP_IREQREPLY:
1143 case ICMP_MASKREPLY:
1144 proto_tree_add_text(icmp_tree, tvb, 4, 2, "Identifier: 0x%04x",
1145 tvb_get_ntohs(tvb, 4));
1146 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Sequence number: %02x:%02x",
1147 tvb_get_guint8(tvb, 6), tvb_get_guint8(tvb, 7));
1151 switch (icmp_code) {
1152 case ICMP_FRAG_NEEDED:
1153 proto_tree_add_text(icmp_tree, tvb, 6, 2, "MTU of next hop: %u",
1154 tvb_get_ntohs(tvb, 6));
1159 case ICMP_RTRADVERT:
1160 num_addrs = tvb_get_guint8(tvb, 4);
1161 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1163 addr_entry_size = tvb_get_guint8(tvb, 5);
1164 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1166 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1167 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1170 case ICMP_PARAMPROB:
1171 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1172 tvb_get_guint8(tvb, 4));
1176 proto_tree_add_text(icmp_tree, tvb, 4, 4, "Gateway address: %s",
1177 ip_to_str(tvb_get_ptr(tvb, 4, 4)));
1181 /* Decode the additional information in the packet. */
1182 switch (icmp_type) {
1185 case ICMP_PARAMPROB:
1186 case ICMP_SOURCEQUENCH:
1188 /* Decode the IP header and first 64 bits of data from the
1191 XXX - for now, just display it as data; not all dissection
1192 routines can handle a short packet without exploding. */
1193 dissect_data(tvb, 8, pinfo, icmp_tree);
1196 case ICMP_ECHOREPLY:
1198 dissect_data(tvb, 8, pinfo, icmp_tree);
1201 case ICMP_RTRADVERT:
1202 if (addr_entry_size == 2) {
1203 for (i = 0; i < num_addrs; i++) {
1204 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1205 "Router address: %s",
1206 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1207 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1208 "Preference level: %u", tvb_get_ntohl(tvb, 12 + (i*8)));
1211 dissect_data(tvb, 8, pinfo, icmp_tree);
1215 case ICMP_TSTAMPREPLY:
1216 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1217 tvb_get_ntohl(tvb, 8));
1218 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1219 tvb_get_ntohl(tvb, 12));
1220 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1221 tvb_get_ntohl(tvb, 16));
1225 case ICMP_MASKREPLY:
1226 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1227 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1234 dissect_igmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1237 proto_tree *igmp_tree;
1241 if (check_col(pinfo->fd, COL_PROTOCOL))
1242 col_set_str(pinfo->fd, COL_PROTOCOL, "IGMP");
1243 if (check_col(pinfo->fd, COL_INFO))
1244 col_clear(pinfo->fd, COL_INFO);
1246 /* Avoids alignment problems on many architectures. */
1247 memcpy(&ih, tvb_get_ptr(tvb, 0, sizeof(e_igmp)), sizeof(e_igmp));
1249 switch (lo_nibble(ih.igmp_v_t)) {
1251 type_str = "Router query";
1254 type_str = "Host response (v1)";
1256 case IGMP_V2_LV_GRP:
1257 type_str = "Leave group (v2)";
1266 type_str = "Host response (v2)";
1268 case IGMP_MTRC_RESP:
1269 type_str = "Traceroute response";
1272 type_str = "Traceroute message";
1275 type_str = "Unknown IGMP";
1278 if (check_col(pinfo->fd, COL_INFO))
1279 col_add_str(pinfo->fd, COL_INFO, type_str);
1281 ti = proto_tree_add_item(tree, proto_igmp, tvb, 0, 8, FALSE);
1282 igmp_tree = proto_item_add_subtree(ti, ett_igmp);
1283 proto_tree_add_uint(igmp_tree, hf_igmp_version, tvb, 0, 1,
1284 hi_nibble(ih.igmp_v_t));
1285 proto_tree_add_uint_format(igmp_tree, hf_igmp_type, tvb, 0 , 1,
1286 lo_nibble(ih.igmp_v_t),
1288 lo_nibble(ih.igmp_v_t), type_str);
1289 proto_tree_add_item(igmp_tree, hf_igmp_unused, tvb, 1, 1, FALSE);
1290 proto_tree_add_item(igmp_tree, hf_igmp_checksum, tvb, 2, 2, FALSE);
1291 proto_tree_add_ipv4(igmp_tree, hf_igmp_group, tvb, 4, 4, ih.igmp_gaddr);
1296 proto_register_igmp(void)
1298 static hf_register_info hf[] = {
1301 { "Version", "igmp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1305 { "Type", "igmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1309 { "Unused", "igmp.unused", FT_UINT8, BASE_HEX, NULL, 0x0,
1312 { &hf_igmp_checksum,
1313 { "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1317 { "Group address", "igmp.group", FT_IPv4, BASE_NONE, NULL, 0x0,
1320 static gint *ett[] = {
1324 proto_igmp = proto_register_protocol("Internet Group Management Protocol",
1326 proto_register_field_array(proto_igmp, hf, array_length(hf));
1327 proto_register_subtree_array(ett, array_length(ett));
1331 proto_reg_handoff_igmp(void)
1333 dissector_add("ip.proto", IP_PROTO_IGMP, dissect_igmp, proto_igmp);
1337 proto_register_ip(void)
1339 static hf_register_info hf[] = {
1342 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1346 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1350 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1353 { &hf_ip_dsfield_dscp,
1354 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1355 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1358 { &hf_ip_dsfield_ect,
1359 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1363 { &hf_ip_dsfield_ce,
1364 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1369 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1372 { &hf_ip_tos_precedence,
1373 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1378 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1382 { &hf_ip_tos_throughput,
1383 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1387 { &hf_ip_tos_reliability,
1388 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1393 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1398 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1402 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1406 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1410 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1414 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1418 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1422 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1426 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1429 { &hf_ip_frag_offset,
1430 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1434 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1438 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1442 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1445 { &hf_ip_checksum_bad,
1446 { "Bad Header checksum", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1449 static gint *ett[] = {
1456 &ett_ip_option_route,
1457 &ett_ip_option_timestamp,
1459 module_t *ip_module;
1461 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1462 proto_register_field_array(proto_ip, hf, array_length(hf));
1463 proto_register_subtree_array(ett, array_length(ett));
1465 /* subdissector code */
1466 ip_dissector_table = register_dissector_table("ip.proto");
1468 /* Register a configuration option for decoding TOS as DSCP */
1469 ip_module = prefs_register_protocol(proto_ip, NULL);
1470 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1471 "Decode IPv4 TOS field as DiffServ field",
1472 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1475 register_dissector("ip", dissect_ip, proto_ip);
1479 proto_reg_handoff_ip(void)
1481 dissector_add("ethertype", ETHERTYPE_IP, dissect_ip, proto_ip);
1482 dissector_add("ppp.protocol", PPP_IP, dissect_ip, proto_ip);
1483 dissector_add("ppp.protocol", ETHERTYPE_IP, dissect_ip, proto_ip);
1484 dissector_add("gre.proto", ETHERTYPE_IP, dissect_ip, proto_ip);
1485 dissector_add("gre.proto", GRE_WCCP, dissect_ip, proto_ip);
1486 dissector_add("llc.dsap", SAP_IP, dissect_ip, proto_ip);
1487 dissector_add("ip.proto", IP_PROTO_IPIP, dissect_ip, proto_ip);
1488 dissector_add("null.type", BSD_AF_INET, dissect_ip, proto_ip);
1489 dissector_add("chdlctype", ETHERTYPE_IP, dissect_ip, proto_ip);
1490 dissector_add("fr.ietf", NLPID_IP, dissect_ip, proto_ip);
1494 proto_register_icmp(void)
1496 static hf_register_info hf[] = {
1499 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1503 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1506 { &hf_icmp_checksum,
1507 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1510 { &hf_icmp_checksum_bad,
1511 { "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1514 static gint *ett[] = {
1518 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
1520 proto_register_field_array(proto_icmp, hf, array_length(hf));
1521 proto_register_subtree_array(ett, array_length(ett));
1525 proto_reg_handoff_icmp(void)
1527 dissector_add("ip.proto", IP_PROTO_ICMP, dissect_icmp, proto_icmp);