2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.104 2000/10/21 04:34:47 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"
52 #include "packet-ip.h"
53 #include "packet-ipsec.h"
55 static void dissect_icmp(const u_char *, int, frame_data *, proto_tree *);
56 static void dissect_igmp(tvbuff_t *, packet_info *, proto_tree *);
58 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
59 gboolean g_ip_dscp_actif = TRUE;
61 static int proto_ip = -1;
62 static int hf_ip_version = -1;
63 static int hf_ip_hdr_len = -1;
64 static int hf_ip_dsfield = -1;
65 static int hf_ip_dsfield_dscp = -1;
66 static int hf_ip_dsfield_ect = -1;
67 static int hf_ip_dsfield_ce = -1;
68 static int hf_ip_tos = -1;
69 static int hf_ip_tos_precedence = -1;
70 static int hf_ip_tos_delay = -1;
71 static int hf_ip_tos_throughput = -1;
72 static int hf_ip_tos_reliability = -1;
73 static int hf_ip_tos_cost = -1;
74 static int hf_ip_len = -1;
75 static int hf_ip_id = -1;
76 static int hf_ip_dst = -1;
77 static int hf_ip_src = -1;
78 static int hf_ip_addr = -1;
79 static int hf_ip_flags = -1;
80 static int hf_ip_flags_df = -1;
81 static int hf_ip_flags_mf = -1;
82 static int hf_ip_frag_offset = -1;
83 static int hf_ip_ttl = -1;
84 static int hf_ip_proto = -1;
85 static int hf_ip_checksum = -1;
87 static gint ett_ip = -1;
88 static gint ett_ip_dsfield = -1;
89 static gint ett_ip_tos = -1;
90 static gint ett_ip_off = -1;
91 static gint ett_ip_options = -1;
92 static gint ett_ip_option_sec = -1;
93 static gint ett_ip_option_route = -1;
94 static gint ett_ip_option_timestamp = -1;
96 /* Used by IPv6 as well, so not static */
97 dissector_table_t ip_dissector_table;
99 static int proto_igmp = -1;
100 static int hf_igmp_version = -1;
101 static int hf_igmp_type = -1;
102 static int hf_igmp_unused = -1;
103 static int hf_igmp_checksum = -1;
104 static int hf_igmp_group = -1;
106 static gint ett_igmp = -1;
108 static int proto_icmp = -1;
109 static int hf_icmp_type = -1;
110 static int hf_icmp_code = -1;
111 static int hf_icmp_checksum = -1;
113 static gint ett_icmp = -1;
115 /* ICMP structs and definitions */
116 typedef struct _e_icmp {
121 struct { /* Address mask request/reply */
126 struct { /* Timestap request/reply */
133 guint32 zero; /* Unreachable */
137 #define ICMP_ECHOREPLY 0
138 #define ICMP_UNREACH 3
139 #define ICMP_SOURCEQUENCH 4
140 #define ICMP_REDIRECT 5
142 #define ICMP_RTRADVERT 9
143 #define ICMP_RTRSOLICIT 10
144 #define ICMP_TIMXCEED 11
145 #define ICMP_PARAMPROB 12
146 #define ICMP_TSTAMP 13
147 #define ICMP_TSTAMPREPLY 14
149 #define ICMP_IREQREPLY 16
150 #define ICMP_MASKREQ 17
151 #define ICMP_MASKREPLY 18
153 /* ICMP UNREACHABLE */
155 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
156 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
157 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
158 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
159 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
160 #define ICMP_SR_FAILED 5 /* Source Route failed */
161 #define ICMP_NET_UNKNOWN 6
162 #define ICMP_HOST_UNKNOWN 7
163 #define ICMP_HOST_ISOLATED 8
164 #define ICMP_NET_ANO 9
165 #define ICMP_HOST_ANO 10
166 #define ICMP_NET_UNR_TOS 11
167 #define ICMP_HOST_UNR_TOS 12
168 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
169 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
170 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
173 /* IGMP structs and definitions */
174 typedef struct _e_igmp {
175 guint8 igmp_v_t; /* combines igmp_v and igmp_t */
181 #define IGMP_M_QRY 0x01
182 #define IGMP_V1_M_RPT 0x02
183 #define IGMP_V2_LV_GRP 0x07
184 #define IGMP_DVMRP 0x03
185 #define IGMP_PIM 0x04
186 #define IGMP_V2_M_RPT 0x06
187 #define IGMP_MTRC_RESP 0x1e
188 #define IGMP_MTRC 0x1f
190 /* IP structs and definitions */
194 guint8 ip_v_hl; /* combines ip_v and ip_hl */
206 /* Offsets of fields within an IP header. */
218 /* Minimum IP header length. */
219 #define IPH_MIN_LEN 20
222 #define IP_CE 0x8000 /* Flag: "Congestion" */
223 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
224 #define IP_MF 0x2000 /* Flag: "More Fragments" */
225 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
227 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
228 #define IPDSFIELD_DSCP_MASK 0xFC
229 #define IPDSFIELD_ECN_MASK 0x03
230 #define IPDSFIELD_DSCP_SHIFT 2
231 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
232 #define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
233 #define IPDSFIELD_DSCP_DEFAULT 0x00
234 #define IPDSFIELD_DSCP_CS1 0x08
235 #define IPDSFIELD_DSCP_CS2 0x10
236 #define IPDSFIELD_DSCP_CS3 0x18
237 #define IPDSFIELD_DSCP_CS4 0x20
238 #define IPDSFIELD_DSCP_CS5 0x28
239 #define IPDSFIELD_DSCP_CS6 0x30
240 #define IPDSFIELD_DSCP_CS7 0x38
241 #define IPDSFIELD_DSCP_AF11 0x0A
242 #define IPDSFIELD_DSCP_AF12 0x0C
243 #define IPDSFIELD_DSCP_AF13 0x0E
244 #define IPDSFIELD_DSCP_AF21 0x12
245 #define IPDSFIELD_DSCP_AF22 0x14
246 #define IPDSFIELD_DSCP_AF23 0x16
247 #define IPDSFIELD_DSCP_AF31 0x1A
248 #define IPDSFIELD_DSCP_AF32 0x1C
249 #define IPDSFIELD_DSCP_AF33 0x1E
250 #define IPDSFIELD_DSCP_AF41 0x22
251 #define IPDSFIELD_DSCP_AF42 0x24
252 #define IPDSFIELD_DSCP_AF43 0x26
253 #define IPDSFIELD_DSCP_EF 0x2E
254 #define IPDSFIELD_ECT_MASK 0x02
255 #define IPDSFIELD_CE_MASK 0x01
257 /* IP TOS, superseded by the DS Field, RFC 2474. */
258 #define IPTOS_TOS_MASK 0x1E
259 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
260 #define IPTOS_NONE 0x00
261 #define IPTOS_LOWCOST 0x02
262 #define IPTOS_RELIABILITY 0x04
263 #define IPTOS_THROUGHPUT 0x08
264 #define IPTOS_LOWDELAY 0x10
265 #define IPTOS_SECURITY 0x1E
267 #define IPTOS_PREC_MASK 0xE0
268 #define IPTOS_PREC_SHIFT 5
269 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
270 #define IPTOS_PREC_NETCONTROL 7
271 #define IPTOS_PREC_INTERNETCONTROL 6
272 #define IPTOS_PREC_CRITIC_ECP 5
273 #define IPTOS_PREC_FLASHOVERRIDE 4
274 #define IPTOS_PREC_FLASH 3
275 #define IPTOS_PREC_IMMEDIATE 2
276 #define IPTOS_PREC_PRIORITY 1
277 #define IPTOS_PREC_ROUTINE 0
280 #define IPOPT_COPY 0x80
282 #define IPOPT_CONTROL 0x00
283 #define IPOPT_RESERVED1 0x20
284 #define IPOPT_MEASUREMENT 0x40
285 #define IPOPT_RESERVED2 0x60
287 #define IPOPT_END (0 |IPOPT_CONTROL)
288 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
289 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
290 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
291 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
292 #define IPOPT_RR (7 |IPOPT_CONTROL)
293 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
294 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
295 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
297 /* IP option lengths */
298 #define IPOLEN_SEC 11
299 #define IPOLEN_LSRR_MIN 3
300 #define IPOLEN_TIMESTAMP_MIN 5
301 #define IPOLEN_RR_MIN 3
303 #define IPOLEN_SSRR_MIN 3
305 #define IPSEC_UNCLASSIFIED 0x0000
306 #define IPSEC_CONFIDENTIAL 0xF135
307 #define IPSEC_EFTO 0x789A
308 #define IPSEC_MMMM 0xBC4D
309 #define IPSEC_RESTRICTED 0xAF13
310 #define IPSEC_SECRET 0xD788
311 #define IPSEC_TOPSECRET 0x6BC5
312 #define IPSEC_RESERVED1 0x35E2
313 #define IPSEC_RESERVED2 0x9AF1
314 #define IPSEC_RESERVED3 0x4D78
315 #define IPSEC_RESERVED4 0x24BD
316 #define IPSEC_RESERVED5 0x135E
317 #define IPSEC_RESERVED6 0x89AF
318 #define IPSEC_RESERVED7 0xC4D6
319 #define IPSEC_RESERVED8 0xE26B
321 #define IPOPT_TS_TSONLY 0 /* timestamps only */
322 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
323 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
327 capture_ip(const u_char *pd, int offset, packet_counts *ld) {
328 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
332 switch (pd[offset + 9]) {
360 dissect_ipopt_security(const ip_tcp_opt *optp, const u_char *opd, int offset,
361 guint optlen, proto_tree *opt_tree)
363 proto_tree *field_tree = NULL;
366 static const value_string secl_vals[] = {
367 {IPSEC_UNCLASSIFIED, "Unclassified"},
368 {IPSEC_CONFIDENTIAL, "Confidential"},
369 {IPSEC_EFTO, "EFTO" },
370 {IPSEC_MMMM, "MMMM" },
371 {IPSEC_RESTRICTED, "Restricted" },
372 {IPSEC_SECRET, "Secret" },
373 {IPSEC_TOPSECRET, "Top secret" },
374 {IPSEC_RESERVED1, "Reserved" },
375 {IPSEC_RESERVED2, "Reserved" },
376 {IPSEC_RESERVED3, "Reserved" },
377 {IPSEC_RESERVED4, "Reserved" },
378 {IPSEC_RESERVED5, "Reserved" },
379 {IPSEC_RESERVED6, "Reserved" },
380 {IPSEC_RESERVED7, "Reserved" },
381 {IPSEC_RESERVED8, "Reserved" },
384 tf = proto_tree_add_text(opt_tree, NullTVB, offset, optlen, "%s:", optp->name);
385 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
389 proto_tree_add_text(field_tree, NullTVB, offset, 2,
390 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
395 proto_tree_add_text(field_tree, NullTVB, offset, 2,
396 "Compartments: %u", val);
400 proto_tree_add_text(field_tree, NullTVB, offset, 2,
401 "Handling restrictions: %c%c", opd[0], opd[1]);
405 proto_tree_add_text(field_tree, NullTVB, offset, 3,
406 "Transmission control code: %c%c%c", opd[0], opd[1], opd[2]);
410 dissect_ipopt_route(const ip_tcp_opt *optp, const u_char *opd, int offset,
411 guint optlen, proto_tree *opt_tree)
413 proto_tree *field_tree = NULL;
419 tf = proto_tree_add_text(opt_tree, NullTVB, offset, optlen, "%s (%u bytes)",
421 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
423 optoffset += 2; /* skip past type and length */
424 optlen -= 2; /* subtract size of type and length */
427 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
428 "Pointer: %d%s", ptr,
429 ((ptr < 4) ? " (points before first address)" :
430 ((ptr & 3) ? " (points to middle of address)" : "")));
434 ptr--; /* ptr is 1-origin */
438 proto_tree_add_text(field_tree, NullTVB, offset, optlen,
439 "(suboption would go past end of option)");
443 /* Avoids alignment problems on many architectures. */
444 memcpy((char *)&addr, (char *)opd, sizeof(addr));
446 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 4,
448 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
449 ((optoffset == ptr) ? " <- (current)" : ""));
457 dissect_ipopt_sid(const ip_tcp_opt *optp, const u_char *opd, int offset,
458 guint optlen, proto_tree *opt_tree)
460 proto_tree_add_text(opt_tree, NullTVB, offset, optlen,
461 "%s: %d", optp->name, pntohs(opd));
466 dissect_ipopt_timestamp(const ip_tcp_opt *optp, const u_char *opd,
467 int offset, guint optlen, proto_tree *opt_tree)
469 proto_tree *field_tree = NULL;
474 static const value_string flag_vals[] = {
475 {IPOPT_TS_TSONLY, "Time stamps only" },
476 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
477 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
482 tf = proto_tree_add_text(opt_tree, NullTVB, offset, optlen, "%s:", optp->name);
483 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
485 optoffset += 2; /* skip past type and length */
486 optlen -= 2; /* subtract size of type and length */
489 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
490 "Pointer: %d%s", ptr,
491 ((ptr < 5) ? " (points before first address)" :
492 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
496 ptr--; /* ptr is 1-origin */
499 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
500 "Overflow: %d", flg >> 4);
502 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
503 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
509 if (flg == IPOPT_TS_TSANDADDR) {
510 /* XXX - check whether it goes past end of packet */
512 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, optlen,
513 "(suboption would go past end of option)");
516 memcpy((char *)&addr, (char *)opd, sizeof(addr));
521 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 8,
522 "Address = %s, time stamp = %u",
523 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
528 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, optlen,
529 "(suboption would go past end of option)");
532 /* XXX - check whether it goes past end of packet */
536 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 4,
537 "Time stamp = %u", ts);
543 static const ip_tcp_opt ipopts[] = {
566 dissect_ipopt_security
570 "Strict source route",
571 &ett_ip_option_route,
578 "Loose source route",
579 &ett_ip_option_route,
587 &ett_ip_option_route,
603 &ett_ip_option_timestamp,
605 IPOLEN_TIMESTAMP_MIN,
606 dissect_ipopt_timestamp
610 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
612 /* Dissect the IP or TCP options in a packet. */
614 dissect_ip_tcp_options(const u_char *opd, int offset, guint length,
615 const ip_tcp_opt *opttab, int nopts, int eol,
616 proto_tree *opt_tree)
619 const ip_tcp_opt *optp;
620 opt_len_type len_type;
623 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
624 void (*dissect)(const struct ip_tcp_opt *, const u_char *,
625 int, guint, proto_tree *);
630 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
631 if (optp->optcode == opt)
634 if (optp == &opttab[nopts]) {
635 /* We assume that the only NO_LENGTH options are EOL and NOP options,
636 so that we can treat unknown options as VARIABLE_LENGTH with a
637 minimum of 2, and at least be able to move on to the next option
638 by using the length in the option. */
639 optp = NULL; /* indicate that we don't know this option */
640 len_type = VARIABLE_LENGTH;
642 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
646 len_type = optp->len_type;
647 optlen = optp->optlen;
649 dissect = optp->dissect;
651 --length; /* account for type byte */
652 if (len_type != NO_LENGTH) {
653 /* Option has a length. Is it in the packet? */
655 /* Bogus - packet must at least include option code byte and
657 proto_tree_add_text(opt_tree, NullTVB, offset, 1,
658 "%s (length byte past end of options)", name);
661 len = *opd++; /* total including type, len */
662 --length; /* account for length byte */
664 /* Bogus - option length is too short to include option code and
666 proto_tree_add_text(opt_tree, NullTVB, offset, 2,
667 "%s (with too-short option length = %u byte%s)", name,
668 len, plurality(len, "", "s"));
670 } else if (len - 2 > length) {
671 /* Bogus - option goes past the end of the header. */
672 proto_tree_add_text(opt_tree, NullTVB, offset, length,
673 "%s (option length = %u byte%s says option goes past end of options)",
674 name, len, plurality(len, "", "s"));
676 } else if (len_type == FIXED_LENGTH && len != optlen) {
677 /* Bogus - option length isn't what it's supposed to be for this
679 proto_tree_add_text(opt_tree, NullTVB, offset, len,
680 "%s (with option length = %u byte%s; should be %u)", name,
681 len, plurality(len, "", "s"), optlen);
683 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
684 /* Bogus - option length is less than what it's supposed to be for
686 proto_tree_add_text(opt_tree, NullTVB, offset, len,
687 "%s (with option length = %u byte%s; should be >= %u)", name,
688 len, plurality(len, "", "s"), optlen);
692 proto_tree_add_text(opt_tree, NullTVB, offset, len, "%s (%u byte%s)",
693 name, len, plurality(len, "", "s"));
695 if (dissect != NULL) {
696 /* Option has a dissector. */
697 (*dissect)(optp, opd, offset, len, opt_tree);
699 /* Option has no data, hence no dissector. */
700 proto_tree_add_text(opt_tree, NullTVB, offset, len, "%s", name);
703 len -= 2; /* subtract size of type and length */
709 proto_tree_add_text(opt_tree, NullTVB, offset, 1, "%s", name);
717 static const value_string dscp_vals[] = {
718 { IPDSFIELD_DSCP_DEFAULT, "Default" },
719 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
720 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
721 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
722 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
723 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
724 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
725 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
726 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
727 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
728 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
729 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
730 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
731 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
732 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
733 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
734 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
735 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
736 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
737 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
738 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
741 static const value_string precedence_vals[] = {
742 { IPTOS_PREC_ROUTINE, "routine" },
743 { IPTOS_PREC_PRIORITY, "priority" },
744 { IPTOS_PREC_IMMEDIATE, "immediate" },
745 { IPTOS_PREC_FLASH, "flash" },
746 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
747 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
748 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
749 { IPTOS_PREC_NETCONTROL, "network control" },
752 static const value_string iptos_vals[] = {
753 { IPTOS_NONE, "None" },
754 { IPTOS_LOWCOST, "Minimize cost" },
755 { IPTOS_RELIABILITY, "Maximize reliability" },
756 { IPTOS_THROUGHPUT, "Maximize throughput" },
757 { IPTOS_LOWDELAY, "Minimize delay" },
758 { IPTOS_SECURITY, "Maximize security" },
762 static const true_false_string tos_set_low = {
767 static const true_false_string tos_set_high = {
772 static const true_false_string flags_set_truth = {
777 static guint16 ip_checksum(const guint8 *ptr, int len)
780 const unsigned char *Ptr, *PtrEnd;
784 for (Ptr = ptr; Ptr < PtrEnd; Ptr += 2) {
787 Sum = (Sum & 0xFFFF) + (Sum >> 16);
788 Sum = (Sum & 0xFFFF) + (Sum >> 16);
790 return (guint16)~Sum;
793 static guint16 ip_checksum_shouldbe(guint16 sum, guint16 computed_sum)
798 * The value that should have gone into the checksum field
799 * is the negative of the value gotten by summing up everything
800 * *but* the checksum field.
802 * We can compute that by subtracting the value of the checksum
803 * field from the sum of all the data in the packet, and then
804 * computing the negative of that value.
806 * "sum" is the value of the checksum field, and "computed_sum"
807 * is the negative of the sum of all the data in the packets,
808 * so that's -(-computed_sum - sum), or (sum + computed_sum).
810 * All the arithmetic in question is one's complement, so the
811 * addition must include an end-around carry; we do this by
812 * doing the arithmetic in 32 bits (with no sign-extension),
813 * and then adding the upper 16 bits of the sum, which contain
814 * the carry, to the lower 16 bits of the sum, and then do it
815 * again in case *that* sum produced a carry.
818 shouldbe += computed_sum;
819 shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
820 shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
825 dissect_ip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
827 proto_tree *ip_tree, *field_tree;
829 guint hlen, optlen, len;
834 OLD_CHECK_DISPLAY_AS_DATA(proto_ip, pd, offset, fd, tree);
836 /* To do: check for errs, etc. */
837 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
838 old_dissect_data(pd, offset, fd, tree);
842 /* Avoids alignment problems on many architectures. */
843 memcpy(&iph, &pd[offset], sizeof(e_ip));
844 iph.ip_len = ntohs(iph.ip_len);
845 iph.ip_id = ntohs(iph.ip_id);
846 iph.ip_off = ntohs(iph.ip_off);
847 iph.ip_sum = ntohs(iph.ip_sum);
849 /* Length of IP datagram plus headers above it. */
850 len = iph.ip_len + offset;
852 /* Set the payload and captured-payload lengths to the minima of (the
853 IP length plus the length of the headers above it) and the frame
857 if (pi.captured_len > len)
858 pi.captured_len = len;
860 /* XXX - check to make sure this is at least IPH_MIN_LEN. */
861 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
864 ti = proto_tree_add_item(tree, proto_ip, NullTVB, offset, hlen, FALSE);
865 ip_tree = proto_item_add_subtree(ti, ett_ip);
867 proto_tree_add_uint(ip_tree, hf_ip_version, NullTVB, offset, 1, hi_nibble(iph.ip_v_hl));
868 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, NullTVB, offset, 1, hlen,
869 "Header length: %u bytes", hlen);
871 if (g_ip_dscp_actif) {
872 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, NullTVB, offset + 1, 1, iph.ip_tos,
873 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph.ip_tos,
874 IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
875 "Unknown DSCP"),IPDSFIELD_ECN(iph.ip_tos));
877 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
878 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, NullTVB, offset + 1, 1, iph.ip_tos);
879 proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, NullTVB, offset + 1, 1, iph.ip_tos);
880 proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, NullTVB, offset + 1, 1, iph.ip_tos);
882 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, NullTVB, offset + 1, 1, iph.ip_tos,
883 "Type of service: 0x%02x (%s)", iph.ip_tos,
884 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
886 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
887 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, NullTVB, offset + 1, 1, iph.ip_tos);
888 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, NullTVB, offset + 1, 1, iph.ip_tos);
889 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, NullTVB, offset + 1, 1, iph.ip_tos);
890 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, NullTVB, offset + 1, 1, iph.ip_tos);
891 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, NullTVB, offset + 1, 1, iph.ip_tos);
893 proto_tree_add_uint(ip_tree, hf_ip_len, NullTVB, offset + 2, 2, iph.ip_len);
894 proto_tree_add_uint(ip_tree, hf_ip_id, NullTVB, offset + 4, 2, iph.ip_id);
896 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
897 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, NullTVB, offset + 6, 1, flags);
898 field_tree = proto_item_add_subtree(tf, ett_ip_off);
899 proto_tree_add_boolean(field_tree, hf_ip_flags_df, NullTVB, offset + 6, 1, flags),
900 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, NullTVB, offset + 6, 1, flags),
902 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, NullTVB, offset + 6, 2,
903 (iph.ip_off & IP_OFFSET)*8);
904 proto_tree_add_uint(ip_tree, hf_ip_ttl, NullTVB, offset + 8, 1, iph.ip_ttl);
905 proto_tree_add_uint_format(ip_tree, hf_ip_proto, NullTVB, offset + 9, 1, iph.ip_p,
906 "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
908 ipsum = ip_checksum(&pd[offset], hlen);
910 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, NullTVB, offset + 10, 2, iph.ip_sum,
911 "Header checksum: 0x%04x (correct)", iph.ip_sum);
914 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, NullTVB, offset + 10, 2, iph.ip_sum,
915 "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph.ip_sum,
916 ip_checksum_shouldbe(iph.ip_sum, ipsum));
919 proto_tree_add_ipv4(ip_tree, hf_ip_src, NullTVB, offset + 12, 4, iph.ip_src);
920 proto_tree_add_ipv4(ip_tree, hf_ip_dst, NullTVB, offset + 16, 4, iph.ip_dst);
921 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, NullTVB, offset + 12, 4, iph.ip_src);
922 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, NullTVB, offset + 16, 4, iph.ip_dst);
924 /* Decode IP options, if any. */
925 if (hlen > sizeof (e_ip)) {
926 /* There's more than just the fixed-length header. Decode the
928 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
929 tf = proto_tree_add_text(ip_tree, NullTVB, offset + 20, optlen,
930 "Options: (%u bytes)", optlen);
931 field_tree = proto_item_add_subtree(tf, ett_ip_options);
932 dissect_ip_tcp_options(&pd[offset + 20], offset + 20, optlen,
933 ipopts, N_IP_OPTS, IPOPT_END, field_tree);
937 pi.ipproto = iph.ip_p;
938 pi.iplen = iph.ip_len;
939 pi.iphdrlen = lo_nibble(iph.ip_v_hl);
940 SET_ADDRESS(&pi.net_src, AT_IPv4, 4, &pd[offset + IPH_SRC]);
941 SET_ADDRESS(&pi.src, AT_IPv4, 4, &pd[offset + IPH_SRC]);
942 SET_ADDRESS(&pi.net_dst, AT_IPv4, 4, &pd[offset + IPH_DST]);
943 SET_ADDRESS(&pi.dst, AT_IPv4, 4, &pd[offset + IPH_DST]);
945 /* Skip over header + options */
948 if (iph.ip_off & IP_OFFSET) {
950 if (check_col(fd, COL_PROTOCOL))
951 col_add_str(fd, COL_PROTOCOL, "IP");
952 if (check_col(fd, COL_INFO))
953 col_add_fstr(fd, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
954 ipprotostr(iph.ip_p), iph.ip_p, (iph.ip_off & IP_OFFSET) * 8);
955 old_dissect_data(pd, offset, fd, tree);
959 /* do lookup with the subdissector table */
960 if (!old_dissector_try_port(ip_dissector_table, nxt, pd, offset, fd, tree)) {
961 /* Unknown protocol */
962 if (check_col(fd, COL_PROTOCOL))
963 col_add_str(fd, COL_PROTOCOL, "IP");
964 if (check_col(fd, COL_INFO))
965 col_add_fstr(fd, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
966 old_dissect_data(pd, offset, fd, tree);
971 static const gchar *unreach_str[] = {"Network unreachable",
973 "Protocol unreachable",
975 "Fragmentation needed",
976 "Source route failed",
977 "Destination network unknown",
978 "Destination host unknown",
979 "Source host isolated",
980 "Network administratively prohibited",
981 "Host administratively prohibited",
982 "Network unreachable for TOS",
983 "Host unreachable for TOS",
984 "Communication administratively filtered",
985 "Host precedence violation",
986 "Precedence cutoff in effect"};
988 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
990 static const gchar *redir_str[] = {"Redirect for network",
992 "Redirect for TOS and network",
993 "Redirect for TOS and host"};
995 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
997 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
998 "TTL equals 0 during reassembly"};
1000 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1002 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1004 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1007 dissect_icmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1009 proto_tree *icmp_tree;
1011 guint16 cksum, computed_cksum;
1012 gchar type_str[64], code_str[64] = "";
1013 guint8 num_addrs = 0;
1014 guint8 addr_entry_size = 0;
1017 OLD_CHECK_DISPLAY_AS_DATA(proto_icmp, pd, offset, fd, tree);
1019 /* Avoids alignment problems on many architectures. */
1020 memcpy(&ih, &pd[offset], sizeof(e_icmp));
1021 /* To do: check for runts, errs, etc. */
1022 cksum = ntohs(ih.icmp_cksum);
1024 switch (ih.icmp_type) {
1025 case ICMP_ECHOREPLY:
1026 strcpy(type_str, "Echo (ping) reply");
1029 strcpy(type_str, "Destination unreachable");
1030 if (ih.icmp_code < N_UNREACH) {
1031 sprintf(code_str, "(%s)", unreach_str[ih.icmp_code]);
1033 strcpy(code_str, "(Unknown - error?)");
1036 case ICMP_SOURCEQUENCH:
1037 strcpy(type_str, "Source quench (flow control)");
1040 strcpy(type_str, "Redirect");
1041 if (ih.icmp_code < N_REDIRECT) {
1042 sprintf(code_str, "(%s)", redir_str[ih.icmp_code]);
1044 strcpy(code_str, "(Unknown - error?)");
1048 strcpy(type_str, "Echo (ping) request");
1050 case ICMP_RTRADVERT:
1051 strcpy(type_str, "Router advertisement");
1053 case ICMP_RTRSOLICIT:
1054 strcpy(type_str, "Router solicitation");
1057 strcpy(type_str, "Time-to-live exceeded");
1058 if (ih.icmp_code < N_TIMXCEED) {
1059 sprintf(code_str, "(%s)", ttl_str[ih.icmp_code]);
1061 strcpy(code_str, "(Unknown - error?)");
1064 case ICMP_PARAMPROB:
1065 strcpy(type_str, "Parameter problem");
1066 if (ih.icmp_code < N_PARAMPROB) {
1067 sprintf(code_str, "(%s)", par_str[ih.icmp_code]);
1069 strcpy(code_str, "(Unknown - error?)");
1073 strcpy(type_str, "Timestamp request");
1075 case ICMP_TSTAMPREPLY:
1076 strcpy(type_str, "Timestamp reply");
1079 strcpy(type_str, "Information request");
1081 case ICMP_IREQREPLY:
1082 strcpy(type_str, "Information reply");
1085 strcpy(type_str, "Address mask request");
1087 case ICMP_MASKREPLY:
1088 strcpy(type_str, "Address mask reply");
1091 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1094 if (check_col(fd, COL_PROTOCOL))
1095 col_add_str(fd, COL_PROTOCOL, "ICMP");
1096 if (check_col(fd, COL_INFO))
1097 col_add_str(fd, COL_INFO, type_str);
1100 ti = proto_tree_add_item(tree, proto_icmp, NullTVB, offset, END_OF_FRAME, FALSE);
1101 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1102 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, NullTVB, offset, 1,
1105 ih.icmp_type, type_str);
1106 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, NullTVB, offset + 1, 1,
1109 ih.icmp_code, code_str);
1111 if (pi.captured_len >= pi.len) {
1112 /* The packet isn't truncated, so we can checksum it.
1113 XXX - we have to check whether this is part of a fragmented
1114 IP datagram, too.... */
1116 computed_cksum = ip_checksum(&pd[offset], END_OF_FRAME);
1117 if (computed_cksum == 0) {
1118 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, NullTVB,
1121 "Checksum: 0x%04x (correct)", cksum);
1123 proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, NullTVB,
1126 "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1127 cksum, ip_checksum_shouldbe(cksum, computed_cksum));
1130 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, NullTVB,
1135 /* Decode the second 4 bytes of the packet. */
1136 switch (ih.icmp_type) {
1137 case ICMP_ECHOREPLY:
1140 case ICMP_TSTAMPREPLY:
1142 case ICMP_IREQREPLY:
1144 case ICMP_MASKREPLY:
1145 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 2, "Identifier: 0x%04x",
1146 pntohs(&pd[offset + 4]));
1147 proto_tree_add_text(icmp_tree, NullTVB, offset + 6, 2, "Sequence number: %02x:%02x",
1148 pd[offset+6], pd[offset+7]);
1152 switch (ih.icmp_code) {
1153 case ICMP_FRAG_NEEDED:
1154 proto_tree_add_text(icmp_tree, NullTVB, offset + 6, 2, "MTU of next hop: %u",
1155 pntohs(&pd[offset + 6]));
1160 case ICMP_RTRADVERT:
1161 num_addrs = pd[offset + 4];
1162 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 1, "Number of addresses: %u",
1164 addr_entry_size = pd[offset + 5];
1165 proto_tree_add_text(icmp_tree, NullTVB, offset + 5, 1, "Address entry size: %u",
1167 proto_tree_add_text(icmp_tree, NullTVB, offset + 6, 2, "Lifetime: %s",
1168 time_secs_to_str(pntohs(&pd[offset + 6])));
1171 case ICMP_PARAMPROB:
1172 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 1, "Pointer: %u",
1177 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 4, "Gateway address: %s",
1178 ip_to_str((guint8 *)&pd[offset + 4]));
1182 /* Decode the additional information in the packet. */
1183 switch (ih.icmp_type) {
1186 case ICMP_PARAMPROB:
1187 case ICMP_SOURCEQUENCH:
1189 /* Decode the IP header and first 64 bits of data from the
1192 XXX - for now, just display it as data; not all dissection
1193 routines can handle a short packet without exploding. */
1194 old_dissect_data(pd, offset + 8, fd, icmp_tree);
1197 case ICMP_ECHOREPLY:
1199 old_dissect_data(pd, offset + 8, fd, icmp_tree);
1202 case ICMP_RTRADVERT:
1203 if (addr_entry_size == 2) {
1204 for (i = 0; i < num_addrs; i++) {
1205 proto_tree_add_text(icmp_tree, NullTVB, offset + 8 + (i*8), 4,
1206 "Router address: %s",
1207 ip_to_str((guint8 *)&pd[offset + 8 + (i*8)]));
1208 proto_tree_add_text(icmp_tree, NullTVB, offset + 12 + (i*8), 4,
1209 "Preference level: %u", pntohl(&pd[offset + 12 + (i*8)]));
1212 old_dissect_data(pd, offset + 8, fd, icmp_tree);
1216 case ICMP_TSTAMPREPLY:
1217 proto_tree_add_text(icmp_tree, NullTVB, offset + 8, 4, "Originate timestamp: %u",
1218 pntohl(&pd[offset + 8]));
1219 proto_tree_add_text(icmp_tree, NullTVB, offset + 12, 4, "Receive timestamp: %u",
1220 pntohl(&pd[offset + 12]));
1221 proto_tree_add_text(icmp_tree, NullTVB, offset + 16, 4, "Transmit timestamp: %u",
1222 pntohl(&pd[offset + 16]));
1226 case ICMP_MASKREPLY:
1227 proto_tree_add_text(icmp_tree, NullTVB, offset + 8, 4, "Address mask: %s (0x%8x)",
1228 ip_to_str((guint8 *)&pd[offset + 8]), pntohl(&pd[offset + 8]));
1235 dissect_igmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1238 proto_tree *igmp_tree;
1242 CHECK_DISPLAY_AS_DATA(proto_igmp, tvb, pinfo, tree);
1244 pinfo->current_proto = "IGMP";
1245 if (check_col(pinfo->fd, COL_PROTOCOL))
1246 col_add_str(pinfo->fd, COL_PROTOCOL, "IGMP");
1248 /* Avoids alignment problems on many architectures. */
1249 memcpy(&ih, tvb_get_ptr(tvb, 0, sizeof(e_igmp)), sizeof(e_igmp));
1251 switch (lo_nibble(ih.igmp_v_t)) {
1253 type_str = "Router query";
1256 type_str = "Host response (v1)";
1258 case IGMP_V2_LV_GRP:
1259 type_str = "Leave group (v2)";
1268 type_str = "Host response (v2)";
1270 case IGMP_MTRC_RESP:
1271 type_str = "Traceroute response";
1274 type_str = "Traceroute message";
1277 type_str = "Unknown IGMP";
1280 if (check_col(pinfo->fd, COL_INFO))
1281 col_add_str(pinfo->fd, COL_INFO, type_str);
1283 ti = proto_tree_add_item(tree, proto_igmp, tvb, 0, 8, FALSE);
1284 igmp_tree = proto_item_add_subtree(ti, ett_igmp);
1285 proto_tree_add_uint(igmp_tree, hf_igmp_version, tvb, 0, 1,
1286 hi_nibble(ih.igmp_v_t));
1287 proto_tree_add_uint_format(igmp_tree, hf_igmp_type, tvb, 0 , 1,
1288 lo_nibble(ih.igmp_v_t),
1290 lo_nibble(ih.igmp_v_t), type_str);
1291 proto_tree_add_item(igmp_tree, hf_igmp_unused, tvb, 1, 1, FALSE);
1292 proto_tree_add_item(igmp_tree, hf_igmp_checksum, tvb, 2, 2, FALSE);
1293 proto_tree_add_ipv4(igmp_tree, hf_igmp_group, tvb, 4, 4, ih.igmp_gaddr);
1298 proto_register_igmp(void)
1300 static hf_register_info hf[] = {
1303 { "Version", "igmp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1307 { "Type", "igmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1311 { "Unused", "igmp.unused", FT_UINT8, BASE_HEX, NULL, 0x0,
1314 { &hf_igmp_checksum,
1315 { "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1319 { "Group address", "igmp.group", FT_IPv4, BASE_NONE, NULL, 0x0,
1322 static gint *ett[] = {
1326 proto_igmp = proto_register_protocol ("Internet Group Management Protocol", "igmp");
1327 proto_register_field_array(proto_igmp, hf, array_length(hf));
1328 proto_register_subtree_array(ett, array_length(ett));
1332 proto_reg_handoff_igmp(void)
1334 dissector_add("ip.proto", IP_PROTO_IGMP, dissect_igmp);
1338 proto_register_ip(void)
1340 static hf_register_info hf[] = {
1343 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1347 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1351 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1354 { &hf_ip_dsfield_dscp,
1355 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1356 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1359 { &hf_ip_dsfield_ect,
1360 { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1364 { &hf_ip_dsfield_ce,
1365 { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1370 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1373 { &hf_ip_tos_precedence,
1374 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1379 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1383 { &hf_ip_tos_throughput,
1384 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1388 { &hf_ip_tos_reliability,
1389 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1394 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1399 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1403 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1407 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1411 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1415 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1419 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1423 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1427 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1430 { &hf_ip_frag_offset,
1431 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1435 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1439 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1443 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1446 static gint *ett[] = {
1453 &ett_ip_option_route,
1454 &ett_ip_option_timestamp,
1456 module_t *ip_module;
1458 proto_ip = proto_register_protocol ("Internet Protocol", "ip");
1459 proto_register_field_array(proto_ip, hf, array_length(hf));
1460 proto_register_subtree_array(ett, array_length(ett));
1462 /* subdissector code */
1463 ip_dissector_table = register_dissector_table("ip.proto");
1465 /* Register a configuration option for decoding TOS as DSCP */
1466 ip_module = prefs_register_module("ip", "IP", NULL);
1467 prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1468 "Decode IPv4 TOS field as DiffServ field",
1469 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1474 proto_reg_handoff_ip(void)
1476 old_dissector_add("ethertype", ETHERTYPE_IP, dissect_ip);
1477 old_dissector_add("ppp.protocol", PPP_IP, dissect_ip);
1478 old_dissector_add("llc.dsap", SAP_IP, dissect_ip);
1479 old_dissector_add("ip.proto", IP_PROTO_IPV4, dissect_ip);
1480 old_dissector_add("ip.proto", IP_PROTO_IPIP, dissect_ip);
1484 proto_register_icmp(void)
1486 static hf_register_info hf[] = {
1489 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1493 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1496 { &hf_icmp_checksum,
1497 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1500 static gint *ett[] = {
1504 proto_icmp = proto_register_protocol ("Internet Control Message Protocol",
1506 proto_register_field_array(proto_icmp, hf, array_length(hf));
1507 proto_register_subtree_array(ett, array_length(ett));
1511 proto_reg_handoff_icmp(void)
1513 old_dissector_add("ip.proto", IP_PROTO_ICMP, dissect_icmp);