2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.116 2001/01/03 06:55:29 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"
53 #include "packet-ip.h"
54 #include "packet-ipsec.h"
57 static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
58 static void dissect_igmp(tvbuff_t *, packet_info *, proto_tree *);
60 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
61 gboolean g_ip_dscp_actif = TRUE;
63 static int proto_ip = -1;
64 static int hf_ip_version = -1;
65 static int hf_ip_hdr_len = -1;
66 static int hf_ip_dsfield = -1;
67 static int hf_ip_dsfield_dscp = -1;
68 static int hf_ip_dsfield_ect = -1;
69 static int hf_ip_dsfield_ce = -1;
70 static int hf_ip_tos = -1;
71 static int hf_ip_tos_precedence = -1;
72 static int hf_ip_tos_delay = -1;
73 static int hf_ip_tos_throughput = -1;
74 static int hf_ip_tos_reliability = -1;
75 static int hf_ip_tos_cost = -1;
76 static int hf_ip_len = -1;
77 static int hf_ip_id = -1;
78 static int hf_ip_dst = -1;
79 static int hf_ip_src = -1;
80 static int hf_ip_addr = -1;
81 static int hf_ip_flags = -1;
82 static int hf_ip_flags_df = -1;
83 static int hf_ip_flags_mf = -1;
84 static int hf_ip_frag_offset = -1;
85 static int hf_ip_ttl = -1;
86 static int hf_ip_proto = -1;
87 static int hf_ip_checksum = -1;
89 static gint ett_ip = -1;
90 static gint ett_ip_dsfield = -1;
91 static gint ett_ip_tos = -1;
92 static gint ett_ip_off = -1;
93 static gint ett_ip_options = -1;
94 static gint ett_ip_option_sec = -1;
95 static gint ett_ip_option_route = -1;
96 static gint ett_ip_option_timestamp = -1;
98 /* Used by IPv6 as well, so not static */
99 dissector_table_t ip_dissector_table;
101 static int proto_igmp = -1;
102 static int hf_igmp_version = -1;
103 static int hf_igmp_type = -1;
104 static int hf_igmp_unused = -1;
105 static int hf_igmp_checksum = -1;
106 static int hf_igmp_group = -1;
108 static gint ett_igmp = -1;
110 static int proto_icmp = -1;
111 static int hf_icmp_type = -1;
112 static int hf_icmp_code = -1;
113 static int hf_icmp_checksum = -1;
115 static gint ett_icmp = -1;
117 /* ICMP definitions */
119 #define ICMP_ECHOREPLY 0
120 #define ICMP_UNREACH 3
121 #define ICMP_SOURCEQUENCH 4
122 #define ICMP_REDIRECT 5
124 #define ICMP_RTRADVERT 9
125 #define ICMP_RTRSOLICIT 10
126 #define ICMP_TIMXCEED 11
127 #define ICMP_PARAMPROB 12
128 #define ICMP_TSTAMP 13
129 #define ICMP_TSTAMPREPLY 14
131 #define ICMP_IREQREPLY 16
132 #define ICMP_MASKREQ 17
133 #define ICMP_MASKREPLY 18
135 /* ICMP UNREACHABLE */
137 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
138 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
139 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
140 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
141 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
142 #define ICMP_SR_FAILED 5 /* Source Route failed */
143 #define ICMP_NET_UNKNOWN 6
144 #define ICMP_HOST_UNKNOWN 7
145 #define ICMP_HOST_ISOLATED 8
146 #define ICMP_NET_ANO 9
147 #define ICMP_HOST_ANO 10
148 #define ICMP_NET_UNR_TOS 11
149 #define ICMP_HOST_UNR_TOS 12
150 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
151 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
152 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
155 /* IGMP structs and definitions */
156 typedef struct _e_igmp {
157 guint8 igmp_v_t; /* combines igmp_v and igmp_t */
163 #define IGMP_M_QRY 0x01
164 #define IGMP_V1_M_RPT 0x02
165 #define IGMP_V2_LV_GRP 0x07
166 #define IGMP_DVMRP 0x03
167 #define IGMP_PIM 0x04
168 #define IGMP_V2_M_RPT 0x06
169 #define IGMP_MTRC_RESP 0x1e
170 #define IGMP_MTRC 0x1f
172 /* IP structs and definitions */
176 guint8 ip_v_hl; /* combines ip_v and ip_hl */
188 /* Offsets of fields within an IP header. */
200 /* Minimum IP header length. */
201 #define IPH_MIN_LEN 20
204 #define IP_CE 0x8000 /* Flag: "Congestion" */
205 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
206 #define IP_MF 0x2000 /* Flag: "More Fragments" */
207 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
209 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
210 #define IPDSFIELD_DSCP_MASK 0xFC
211 #define IPDSFIELD_ECN_MASK 0x03
212 #define IPDSFIELD_DSCP_SHIFT 2
213 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
214 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
215 #define IPDSFIELD_DSCP_DEFAULT 0x00
216 #define IPDSFIELD_DSCP_CS1 0x08
217 #define IPDSFIELD_DSCP_CS2 0x10
218 #define IPDSFIELD_DSCP_CS3 0x18
219 #define IPDSFIELD_DSCP_CS4 0x20
220 #define IPDSFIELD_DSCP_CS5 0x28
221 #define IPDSFIELD_DSCP_CS6 0x30
222 #define IPDSFIELD_DSCP_CS7 0x38
223 #define IPDSFIELD_DSCP_AF11 0x0A
224 #define IPDSFIELD_DSCP_AF12 0x0C
225 #define IPDSFIELD_DSCP_AF13 0x0E
226 #define IPDSFIELD_DSCP_AF21 0x12
227 #define IPDSFIELD_DSCP_AF22 0x14
228 #define IPDSFIELD_DSCP_AF23 0x16
229 #define IPDSFIELD_DSCP_AF31 0x1A
230 #define IPDSFIELD_DSCP_AF32 0x1C
231 #define IPDSFIELD_DSCP_AF33 0x1E
232 #define IPDSFIELD_DSCP_AF41 0x22
233 #define IPDSFIELD_DSCP_AF42 0x24
234 #define IPDSFIELD_DSCP_AF43 0x26
235 #define IPDSFIELD_DSCP_EF 0x2E
236 #define IPDSFIELD_ECT_MASK 0x02
237 #define IPDSFIELD_CE_MASK 0x01
239 /* IP TOS, superseded by the DS Field, RFC 2474. */
240 #define IPTOS_TOS_MASK 0x1E
241 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
242 #define IPTOS_NONE 0x00
243 #define IPTOS_LOWCOST 0x02
244 #define IPTOS_RELIABILITY 0x04
245 #define IPTOS_THROUGHPUT 0x08
246 #define IPTOS_LOWDELAY 0x10
247 #define IPTOS_SECURITY 0x1E
249 #define IPTOS_PREC_MASK 0xE0
250 #define IPTOS_PREC_SHIFT 5
251 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
252 #define IPTOS_PREC_NETCONTROL 7
253 #define IPTOS_PREC_INTERNETCONTROL 6
254 #define IPTOS_PREC_CRITIC_ECP 5
255 #define IPTOS_PREC_FLASHOVERRIDE 4
256 #define IPTOS_PREC_FLASH 3
257 #define IPTOS_PREC_IMMEDIATE 2
258 #define IPTOS_PREC_PRIORITY 1
259 #define IPTOS_PREC_ROUTINE 0
262 #define IPOPT_COPY 0x80
264 #define IPOPT_CONTROL 0x00
265 #define IPOPT_RESERVED1 0x20
266 #define IPOPT_MEASUREMENT 0x40
267 #define IPOPT_RESERVED2 0x60
269 #define IPOPT_END (0 |IPOPT_CONTROL)
270 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
271 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
272 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
273 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
274 #define IPOPT_RR (7 |IPOPT_CONTROL)
275 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
276 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
277 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
279 /* IP option lengths */
280 #define IPOLEN_SEC 11
281 #define IPOLEN_LSRR_MIN 3
282 #define IPOLEN_TIMESTAMP_MIN 5
283 #define IPOLEN_RR_MIN 3
285 #define IPOLEN_SSRR_MIN 3
288 #define IPSEC_UNCLASSIFIED 0x0000
289 #define IPSEC_CONFIDENTIAL 0xF135
290 #define IPSEC_EFTO 0x789A
291 #define IPSEC_MMMM 0xBC4D
292 #define IPSEC_RESTRICTED 0xAF13
293 #define IPSEC_SECRET 0xD788
294 #define IPSEC_TOPSECRET 0x6BC5
295 #define IPSEC_RESERVED1 0x35E2
296 #define IPSEC_RESERVED2 0x9AF1
297 #define IPSEC_RESERVED3 0x4D78
298 #define IPSEC_RESERVED4 0x24BD
299 #define IPSEC_RESERVED5 0x135E
300 #define IPSEC_RESERVED6 0x89AF
301 #define IPSEC_RESERVED7 0xC4D6
302 #define IPSEC_RESERVED8 0xE26B
304 #define IPOPT_TS_TSONLY 0 /* timestamps only */
305 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
306 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
310 capture_ip(const u_char *pd, int offset, packet_counts *ld) {
311 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
315 switch (pd[offset + 9]) {
343 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
344 guint optlen, frame_data *fd, proto_tree *opt_tree)
346 proto_tree *field_tree = NULL;
349 static const value_string secl_vals[] = {
350 {IPSEC_UNCLASSIFIED, "Unclassified"},
351 {IPSEC_CONFIDENTIAL, "Confidential"},
352 {IPSEC_EFTO, "EFTO" },
353 {IPSEC_MMMM, "MMMM" },
354 {IPSEC_RESTRICTED, "Restricted" },
355 {IPSEC_SECRET, "Secret" },
356 {IPSEC_TOPSECRET, "Top secret" },
357 {IPSEC_RESERVED1, "Reserved" },
358 {IPSEC_RESERVED2, "Reserved" },
359 {IPSEC_RESERVED3, "Reserved" },
360 {IPSEC_RESERVED4, "Reserved" },
361 {IPSEC_RESERVED5, "Reserved" },
362 {IPSEC_RESERVED6, "Reserved" },
363 {IPSEC_RESERVED7, "Reserved" },
364 {IPSEC_RESERVED8, "Reserved" },
367 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
368 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
371 val = tvb_get_ntohs(tvb, offset);
372 proto_tree_add_text(field_tree, tvb, offset, 2,
373 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
376 val = tvb_get_ntohs(tvb, offset);
377 proto_tree_add_text(field_tree, tvb, offset, 2,
378 "Compartments: %u", val);
381 proto_tree_add_text(field_tree, tvb, offset, 2,
382 "Handling restrictions: %c%c",
383 tvb_get_guint8(tvb, offset),
384 tvb_get_guint8(tvb, offset + 1));
387 proto_tree_add_text(field_tree, tvb, offset, 3,
388 "Transmission control code: %c%c%c",
389 tvb_get_guint8(tvb, offset),
390 tvb_get_guint8(tvb, offset + 1),
391 tvb_get_guint8(tvb, offset + 2));
395 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
396 guint optlen, frame_data *fd, proto_tree *opt_tree)
398 proto_tree *field_tree = NULL;
404 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
406 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
408 optoffset += 2; /* skip past type and length */
409 optlen -= 2; /* subtract size of type and length */
411 ptr = tvb_get_guint8(tvb, offset + optoffset);
412 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
413 "Pointer: %d%s", ptr,
414 ((ptr < 4) ? " (points before first address)" :
415 ((ptr & 3) ? " (points to middle of address)" : "")));
418 ptr--; /* ptr is 1-origin */
422 proto_tree_add_text(field_tree, tvb, offset, optlen,
423 "(suboption would go past end of option)");
427 /* Avoids alignment problems on many architectures. */
428 tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
430 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
432 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
433 ((optoffset == ptr) ? " <- (current)" : ""));
440 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
441 guint optlen, frame_data *fd, proto_tree *opt_tree)
443 proto_tree_add_text(opt_tree, tvb, offset, optlen,
444 "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
449 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
450 int offset, guint optlen, frame_data *fd, proto_tree *opt_tree)
452 proto_tree *field_tree = NULL;
457 static const value_string flag_vals[] = {
458 {IPOPT_TS_TSONLY, "Time stamps only" },
459 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
460 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
465 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
466 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
468 optoffset += 2; /* skip past type and length */
469 optlen -= 2; /* subtract size of type and length */
471 ptr = tvb_get_guint8(tvb, offset + optoffset);
472 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
473 "Pointer: %d%s", ptr,
474 ((ptr < 5) ? " (points before first address)" :
475 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
478 ptr--; /* ptr is 1-origin */
480 flg = tvb_get_guint8(tvb, offset + optoffset);
481 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
482 "Overflow: %u", flg >> 4);
484 proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
485 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
490 if (flg == IPOPT_TS_TSANDADDR) {
492 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
493 "(suboption would go past end of option)");
496 tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
497 ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
499 proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
500 "Address = %s, time stamp = %u",
501 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
506 proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
507 "(suboption would go past end of option)");
510 ts = tvb_get_ntohl(tvb, offset + optoffset);
512 proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
513 "Time stamp = %u", ts);
520 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
521 guint optlen, frame_data *fd, proto_tree *opt_tree)
523 /* Router-Alert, as defined by RFC2113 */
524 int opt = tvb_get_ntohs(tvb, offset + 2);
525 static const value_string ra_opts[] = {
526 {0, "Every router examines packet"} };
528 proto_tree_add_text(opt_tree, tvb, offset, optlen,
529 "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
533 static const ip_tcp_opt ipopts[] = {
556 dissect_ipopt_security
560 "Strict source route",
561 &ett_ip_option_route,
568 "Loose source route",
569 &ett_ip_option_route,
577 &ett_ip_option_route,
593 &ett_ip_option_timestamp,
595 IPOLEN_TIMESTAMP_MIN,
596 dissect_ipopt_timestamp
608 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
610 /* Dissect the IP or TCP options in a packet. */
612 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
613 const ip_tcp_opt *opttab, int nopts, int eol,
614 frame_data *fd, proto_tree *opt_tree)
617 const ip_tcp_opt *optp;
618 opt_len_type len_type;
621 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
622 void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
623 int, guint, frame_data *, proto_tree *);
627 opt = tvb_get_guint8(tvb, offset);
628 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
629 if (optp->optcode == opt)
632 if (optp == &opttab[nopts]) {
633 /* We assume that the only NO_LENGTH options are EOL and NOP options,
634 so that we can treat unknown options as VARIABLE_LENGTH with a
635 minimum of 2, and at least be able to move on to the next option
636 by using the length in the option. */
637 optp = NULL; /* indicate that we don't know this option */
638 len_type = VARIABLE_LENGTH;
640 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
644 len_type = optp->len_type;
645 optlen = optp->optlen;
647 dissect = optp->dissect;
649 --length; /* account for type byte */
650 if (len_type != NO_LENGTH) {
651 /* Option has a length. Is it in the packet? */
653 /* Bogus - packet must at least include option code byte and
655 proto_tree_add_text(opt_tree, tvb, offset, 1,
656 "%s (length byte past end of options)", name);
659 len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
660 --length; /* account for length byte */
662 /* Bogus - option length is too short to include option code and
664 proto_tree_add_text(opt_tree, tvb, offset, 2,
665 "%s (with too-short option length = %u byte%s)", name,
666 len, plurality(len, "", "s"));
668 } else if (len - 2 > length) {
669 /* Bogus - option goes past the end of the header. */
670 proto_tree_add_text(opt_tree, tvb, offset, length,
671 "%s (option length = %u byte%s says option goes past end of options)",
672 name, len, plurality(len, "", "s"));
674 } else if (len_type == FIXED_LENGTH && len != optlen) {
675 /* Bogus - option length isn't what it's supposed to be for this
677 proto_tree_add_text(opt_tree, tvb, offset, len,
678 "%s (with option length = %u byte%s; should be %u)", name,
679 len, plurality(len, "", "s"), optlen);
681 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
682 /* Bogus - option length is less than what it's supposed to be for
684 proto_tree_add_text(opt_tree, tvb, offset, len,
685 "%s (with option length = %u byte%s; should be >= %u)", name,
686 len, plurality(len, "", "s"), optlen);
690 proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
691 name, len, plurality(len, "", "s"));
693 if (dissect != NULL) {
694 /* Option has a dissector. */
695 (*dissect)(optp, tvb, offset, len, fd, opt_tree);
697 /* Option has no data, hence no dissector. */
698 proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
701 len -= 2; /* subtract size of type and length */
706 proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
714 static const value_string dscp_vals[] = {
715 { IPDSFIELD_DSCP_DEFAULT, "Default" },
716 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
717 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
718 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
719 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
720 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
721 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
722 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
723 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
724 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
725 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
726 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
727 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
728 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
729 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
730 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
731 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
732 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
733 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
734 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
735 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
738 static const value_string precedence_vals[] = {
739 { IPTOS_PREC_ROUTINE, "routine" },
740 { IPTOS_PREC_PRIORITY, "priority" },
741 { IPTOS_PREC_IMMEDIATE, "immediate" },
742 { IPTOS_PREC_FLASH, "flash" },
743 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
744 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
745 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
746 { IPTOS_PREC_NETCONTROL, "network control" },
749 static const value_string iptos_vals[] = {
750 { IPTOS_NONE, "None" },
751 { IPTOS_LOWCOST, "Minimize cost" },
752 { IPTOS_RELIABILITY, "Maximize reliability" },
753 { IPTOS_THROUGHPUT, "Maximize throughput" },
754 { IPTOS_LOWDELAY, "Minimize delay" },
755 { IPTOS_SECURITY, "Maximize security" },
759 static const true_false_string tos_set_low = {
764 static const true_false_string tos_set_high = {
769 static const true_false_string flags_set_truth = {
774 static guint16 ip_checksum(const guint8 *ptr, int len)
778 cksum_vec[0].ptr = ptr;
779 cksum_vec[0].len = len;
780 return in_cksum(&cksum_vec[0], 1);
784 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
787 proto_tree *ip_tree, *field_tree;
790 guint hlen, optlen, len, payload_len, reported_payload_len, padding;
796 CHECK_DISPLAY_AS_DATA(proto_ip, tvb, pinfo, tree);
798 pinfo->current_proto = "IP";
800 if (check_col(pinfo->fd, COL_PROTOCOL))
801 col_set_str(pinfo->fd, COL_PROTOCOL, "IP");
802 if (check_col(pinfo->fd, COL_INFO))
803 col_clear(pinfo->fd, COL_INFO);
805 /* Avoids alignment problems on many architectures. */
806 tvb_memcpy(tvb, (guint8 *)&iph, offset, sizeof(e_ip));
807 iph.ip_len = ntohs(iph.ip_len);
808 iph.ip_id = ntohs(iph.ip_id);
809 iph.ip_off = ntohs(iph.ip_off);
810 iph.ip_sum = ntohs(iph.ip_sum);
812 /* Length of payload handed to us. */
813 reported_payload_len = tvb_reported_length(tvb);
814 payload_len = tvb_length(tvb);
816 /* Length of IP datagram. */
819 if (len < reported_payload_len) {
820 /* Adjust the length of this tvbuff to include only the IP datagram.
821 Our caller may use that to determine how much of its packet
823 tvb_set_reported_length(tvb, len);
825 /* Shrink the total payload by the amount of padding. */
826 padding = reported_payload_len - len;
827 if (pinfo->len >= padding)
828 pinfo->len -= padding;
830 /* Shrink the captured payload by the amount of padding in the
831 captured payload (which may be less than the amount of padding,
832 as the padding may not have been captured). */
833 if (len < payload_len) {
834 padding = payload_len - len;
835 if (pinfo->captured_len >= padding)
836 pinfo->captured_len -= padding;
840 /* XXX - check to make sure this is at least IPH_MIN_LEN. */
841 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
844 ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
845 ip_tree = proto_item_add_subtree(ti, ett_ip);
847 proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1, hi_nibble(iph.ip_v_hl));
848 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
849 "Header length: %u bytes", hlen);
851 if (g_ip_dscp_actif) {
852 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph.ip_tos,
853 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph.ip_tos,
854 IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
855 "Unknown DSCP"),IPDSFIELD_ECN(iph.ip_tos));
857 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
858 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph.ip_tos);
859 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph.ip_tos);
860 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph.ip_tos);
862 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph.ip_tos,
863 "Type of service: 0x%02x (%s)", iph.ip_tos,
864 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
866 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
867 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph.ip_tos);
868 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph.ip_tos);
869 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph.ip_tos);
870 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph.ip_tos);
871 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph.ip_tos);
873 proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph.ip_len);
874 proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph.ip_id);
876 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
877 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
878 field_tree = proto_item_add_subtree(tf, ett_ip_off);
879 proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
880 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
882 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
883 (iph.ip_off & IP_OFFSET)*8);
884 proto_tree_add_uint(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, iph.ip_ttl);
885 proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph.ip_p,
886 "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
888 ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
890 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
891 "Header checksum: 0x%04x (correct)", iph.ip_sum);
894 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
895 "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph.ip_sum,
896 in_cksum_shouldbe(iph.ip_sum, ipsum));
899 proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, iph.ip_src);
900 proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, iph.ip_dst);
901 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, iph.ip_src);
902 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, iph.ip_dst);
904 /* Decode IP options, if any. */
905 if (hlen > sizeof (e_ip)) {
906 /* There's more than just the fixed-length header. Decode the
908 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
909 tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
910 "Options: (%u bytes)", optlen);
911 field_tree = proto_item_add_subtree(tf, ett_ip_options);
912 dissect_ip_tcp_options(tvb, offset + 20, optlen,
913 ipopts, N_IP_OPTS, IPOPT_END, pinfo->fd, field_tree);
917 pinfo->ipproto = iph.ip_p;
918 pinfo->iplen = iph.ip_len;
919 pinfo->iphdrlen = lo_nibble(iph.ip_v_hl);
920 SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
921 SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
922 SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
923 SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
925 /* Skip over header + options */
928 if (iph.ip_off & IP_OFFSET) {
930 if (check_col(pinfo->fd, COL_INFO))
931 col_add_fstr(pinfo->fd, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
932 ipprotostr(iph.ip_p), iph.ip_p, (iph.ip_off & IP_OFFSET) * 8);
933 dissect_data(tvb, offset, pinfo, tree);
938 * If this is the first fragment, but not the only fragment,
939 * tell the next protocol that.
941 if (iph.ip_off & IP_MF)
942 pinfo->fragmented = TRUE;
944 pinfo->fragmented = FALSE;
946 /* Hand off to the next protocol.
948 XXX - setting the columns only after trying various dissectors means
949 that if one of those dissectors throws an exception, the frame won't
950 even be labelled as an IP frame; ideally, if a frame being dissected
951 throws an exception, it'll be labelled as a mangled frame of the
953 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
954 if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
955 /* Unknown protocol */
956 if (check_col(pinfo->fd, COL_INFO))
957 col_add_fstr(pinfo->fd, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
958 dissect_data(next_tvb, 0, pinfo, tree);
963 static const gchar *unreach_str[] = {"Network unreachable",
965 "Protocol unreachable",
967 "Fragmentation needed",
968 "Source route failed",
969 "Destination network unknown",
970 "Destination host unknown",
971 "Source host isolated",
972 "Network administratively prohibited",
973 "Host administratively prohibited",
974 "Network unreachable for TOS",
975 "Host unreachable for TOS",
976 "Communication administratively filtered",
977 "Host precedence violation",
978 "Precedence cutoff in effect"};
980 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
982 static const gchar *redir_str[] = {"Redirect for network",
984 "Redirect for TOS and network",
985 "Redirect for TOS and host"};
987 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
989 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
990 "TTL equals 0 during reassembly"};
992 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
994 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
996 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
999 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1001 proto_tree *icmp_tree;
1005 guint length, reported_length;
1006 guint16 cksum, computed_cksum;
1007 gchar type_str[64], code_str[64] = "";
1008 guint8 num_addrs = 0;
1009 guint8 addr_entry_size = 0;
1012 CHECK_DISPLAY_AS_DATA(proto_icmp, tvb, pinfo, tree);
1014 pinfo->current_proto = "ICMP";
1016 if (check_col(pinfo->fd, COL_PROTOCOL))
1017 col_set_str(pinfo->fd, COL_PROTOCOL, "ICMP");
1018 if (check_col(pinfo->fd, COL_INFO))
1019 col_clear(pinfo->fd, COL_INFO);
1021 /* To do: check for runts, errs, etc. */
1022 icmp_type = tvb_get_guint8(tvb, 0);
1023 icmp_code = tvb_get_guint8(tvb, 1);
1024 cksum = tvb_get_ntohs(tvb, 2);
1026 switch (icmp_type) {
1027 case ICMP_ECHOREPLY:
1028 strcpy(type_str, "Echo (ping) reply");
1031 strcpy(type_str, "Destination unreachable");
1032 if (icmp_code < N_UNREACH) {
1033 sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1035 strcpy(code_str, "(Unknown - error?)");
1038 case ICMP_SOURCEQUENCH:
1039 strcpy(type_str, "Source quench (flow control)");
1042 strcpy(type_str, "Redirect");
1043 if (icmp_code < N_REDIRECT) {
1044 sprintf(code_str, "(%s)", redir_str[icmp_code]);
1046 strcpy(code_str, "(Unknown - error?)");
1050 strcpy(type_str, "Echo (ping) request");
1052 case ICMP_RTRADVERT:
1053 strcpy(type_str, "Router advertisement");
1055 case ICMP_RTRSOLICIT:
1056 strcpy(type_str, "Router solicitation");
1059 strcpy(type_str, "Time-to-live exceeded");
1060 if (icmp_code < N_TIMXCEED) {
1061 sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1063 strcpy(code_str, "(Unknown - error?)");
1066 case ICMP_PARAMPROB:
1067 strcpy(type_str, "Parameter problem");
1068 if (icmp_code < N_PARAMPROB) {
1069 sprintf(code_str, "(%s)", par_str[icmp_code]);
1071 strcpy(code_str, "(Unknown - error?)");
1075 strcpy(type_str, "Timestamp request");
1077 case ICMP_TSTAMPREPLY:
1078 strcpy(type_str, "Timestamp reply");
1081 strcpy(type_str, "Information request");
1083 case ICMP_IREQREPLY:
1084 strcpy(type_str, "Information reply");
1087 strcpy(type_str, "Address mask request");
1089 case ICMP_MASKREPLY:
1090 strcpy(type_str, "Address mask reply");
1093 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1096 if (check_col(pinfo->fd, COL_INFO))
1097 col_add_str(pinfo->fd, COL_INFO, type_str);
1100 length = tvb_length(tvb);
1101 reported_length = tvb_reported_length(tvb);
1102 ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1103 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1104 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1107 icmp_type, type_str);
1108 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1111 icmp_code, code_str);
1113 if (!pinfo->fragmented && length >= reported_length) {
1114 /* The packet isn't part of a fragmented datagram and isn't
1115 truncated, so we can checksum it. */
1117 computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1119 if (computed_cksum == 0) {
1120 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1122 "Checksum: 0x%04x (correct)", cksum);
1124 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1126 "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1127 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1130 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1133 /* Decode the second 4 bytes of the packet. */
1134 switch (icmp_type) {
1135 case ICMP_ECHOREPLY:
1138 case ICMP_TSTAMPREPLY:
1140 case ICMP_IREQREPLY:
1142 case ICMP_MASKREPLY:
1143 proto_tree_add_text(icmp_tree, tvb, 4, 2, "Identifier: 0x%04x",
1144 tvb_get_ntohs(tvb, 4));
1145 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Sequence number: %02x:%02x",
1146 tvb_get_guint8(tvb, 6), tvb_get_guint8(tvb, 7));
1150 switch (icmp_code) {
1151 case ICMP_FRAG_NEEDED:
1152 proto_tree_add_text(icmp_tree, tvb, 6, 2, "MTU of next hop: %u",
1153 tvb_get_ntohs(tvb, 6));
1158 case ICMP_RTRADVERT:
1159 num_addrs = tvb_get_guint8(tvb, 4);
1160 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1162 addr_entry_size = tvb_get_guint8(tvb, 5);
1163 proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1165 proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1166 time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1169 case ICMP_PARAMPROB:
1170 proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1171 tvb_get_guint8(tvb, 4));
1175 proto_tree_add_text(icmp_tree, tvb, 4, 4, "Gateway address: %s",
1176 ip_to_str(tvb_get_ptr(tvb, 4, 4)));
1180 /* Decode the additional information in the packet. */
1181 switch (icmp_type) {
1184 case ICMP_PARAMPROB:
1185 case ICMP_SOURCEQUENCH:
1187 /* Decode the IP header and first 64 bits of data from the
1190 XXX - for now, just display it as data; not all dissection
1191 routines can handle a short packet without exploding. */
1192 dissect_data(tvb, 8, pinfo, icmp_tree);
1195 case ICMP_ECHOREPLY:
1197 dissect_data(tvb, 8, pinfo, icmp_tree);
1200 case ICMP_RTRADVERT:
1201 if (addr_entry_size == 2) {
1202 for (i = 0; i < num_addrs; i++) {
1203 proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1204 "Router address: %s",
1205 ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1206 proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1207 "Preference level: %u", tvb_get_ntohl(tvb, 12 + (i*8)));
1210 dissect_data(tvb, 8, pinfo, icmp_tree);
1214 case ICMP_TSTAMPREPLY:
1215 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1216 tvb_get_ntohl(tvb, 8));
1217 proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1218 tvb_get_ntohl(tvb, 12));
1219 proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1220 tvb_get_ntohl(tvb, 16));
1224 case ICMP_MASKREPLY:
1225 proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1226 ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1233 dissect_igmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1236 proto_tree *igmp_tree;
1240 CHECK_DISPLAY_AS_DATA(proto_igmp, tvb, pinfo, tree);
1242 pinfo->current_proto = "IGMP";
1244 if (check_col(pinfo->fd, COL_PROTOCOL))
1245 col_set_str(pinfo->fd, COL_PROTOCOL, "IGMP");
1246 if (check_col(pinfo->fd, COL_INFO))
1247 col_clear(pinfo->fd, COL_INFO);
1249 /* Avoids alignment problems on many architectures. */
1250 memcpy(&ih, tvb_get_ptr(tvb, 0, sizeof(e_igmp)), sizeof(e_igmp));
1252 switch (lo_nibble(ih.igmp_v_t)) {
1254 type_str = "Router query";
1257 type_str = "Host response (v1)";
1259 case IGMP_V2_LV_GRP:
1260 type_str = "Leave group (v2)";
1269 type_str = "Host response (v2)";
1271 case IGMP_MTRC_RESP:
1272 type_str = "Traceroute response";
1275 type_str = "Traceroute message";
1278 type_str = "Unknown IGMP";
1281 if (check_col(pinfo->fd, COL_INFO))
1282 col_add_str(pinfo->fd, COL_INFO, type_str);
1284 ti = proto_tree_add_item(tree, proto_igmp, tvb, 0, 8, FALSE);
1285 igmp_tree = proto_item_add_subtree(ti, ett_igmp);
1286 proto_tree_add_uint(igmp_tree, hf_igmp_version, tvb, 0, 1,
1287 hi_nibble(ih.igmp_v_t));
1288 proto_tree_add_uint_format(igmp_tree, hf_igmp_type, tvb, 0 , 1,
1289 lo_nibble(ih.igmp_v_t),
1291 lo_nibble(ih.igmp_v_t), type_str);
1292 proto_tree_add_item(igmp_tree, hf_igmp_unused, tvb, 1, 1, FALSE);
1293 proto_tree_add_item(igmp_tree, hf_igmp_checksum, tvb, 2, 2, FALSE);
1294 proto_tree_add_ipv4(igmp_tree, hf_igmp_group, tvb, 4, 4, ih.igmp_gaddr);
1299 proto_register_igmp(void)
1301 static hf_register_info hf[] = {
1304 { "Version", "igmp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1308 { "Type", "igmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1312 { "Unused", "igmp.unused", FT_UINT8, BASE_HEX, NULL, 0x0,
1315 { &hf_igmp_checksum,
1316 { "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1320 { "Group address", "igmp.group", FT_IPv4, BASE_NONE, NULL, 0x0,
1323 static gint *ett[] = {
1327 proto_igmp = proto_register_protocol("Internet Group Management Protocol",
1329 proto_register_field_array(proto_igmp, hf, array_length(hf));
1330 proto_register_subtree_array(ett, array_length(ett));
1334 proto_reg_handoff_igmp(void)
1336 dissector_add("ip.proto", IP_PROTO_IGMP, dissect_igmp);
1340 proto_register_ip(void)
1342 static hf_register_info hf[] = {
1345 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1349 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1353 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1356 { &hf_ip_dsfield_dscp,
1357 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1358 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1361 { &hf_ip_dsfield_ect,
1362 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1366 { &hf_ip_dsfield_ce,
1367 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1372 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1375 { &hf_ip_tos_precedence,
1376 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1381 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1385 { &hf_ip_tos_throughput,
1386 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1390 { &hf_ip_tos_reliability,
1391 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1396 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1401 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1405 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1409 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1413 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1417 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1421 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1425 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1429 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1432 { &hf_ip_frag_offset,
1433 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1437 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1441 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1445 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1448 static gint *ett[] = {
1455 &ett_ip_option_route,
1456 &ett_ip_option_timestamp,
1458 module_t *ip_module;
1460 proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1461 proto_register_field_array(proto_ip, hf, array_length(hf));
1462 proto_register_subtree_array(ett, array_length(ett));
1464 /* subdissector code */
1465 ip_dissector_table = register_dissector_table("ip.proto");
1467 /* Register a configuration option for decoding TOS as DSCP */
1468 ip_module = prefs_register_module("ip", "IP", NULL);
1469 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1470 "Decode IPv4 TOS field as DiffServ field",
1471 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1474 register_dissector("ip", dissect_ip);
1478 proto_reg_handoff_ip(void)
1480 dissector_add("ethertype", ETHERTYPE_IP, dissect_ip);
1481 dissector_add("ppp.protocol", PPP_IP, dissect_ip);
1482 dissector_add("ppp.protocol", CISCO_IP, dissect_ip);
1483 dissector_add("llc.dsap", SAP_IP, dissect_ip);
1484 dissector_add("ip.proto", IP_PROTO_IPV4, dissect_ip);
1485 dissector_add("ip.proto", IP_PROTO_IPIP, dissect_ip);
1486 dissector_add("null.type", BSD_AF_INET, dissect_ip);
1490 proto_register_icmp(void)
1492 static hf_register_info hf[] = {
1495 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1499 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1502 { &hf_icmp_checksum,
1503 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1506 static gint *ett[] = {
1510 proto_icmp = proto_register_protocol("Internet Control Message Protocol",
1512 proto_register_field_array(proto_icmp, hf, array_length(hf));
1513 proto_register_subtree_array(ett, array_length(ett));
1517 proto_reg_handoff_icmp(void)
1519 dissector_add("ip.proto", IP_PROTO_ICMP, dissect_icmp);