2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.85 2000/05/11 08:15:11 gram 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>
44 #ifdef NEED_SNPRINTF_H
50 # include "snprintf.h"
56 #include "packet-ip.h"
57 #include "packet-ipsec.h"
59 static void dissect_eigrp(const u_char *, int, frame_data *, proto_tree *);
60 static void dissect_icmp(const u_char *, int, frame_data *, proto_tree *);
61 static void dissect_igmp(const u_char *, int, frame_data *, proto_tree *);
64 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
65 gboolean g_ip_dscp_actif = TRUE;
67 static int proto_ip = -1;
68 static int hf_ip_version = -1;
69 static int hf_ip_hdr_len = -1;
70 static int hf_ip_dsfield = -1;
71 static int hf_ip_dsfield_dscp = -1;
72 static int hf_ip_dsfield_cu = -1;
73 static int hf_ip_tos = -1;
74 static int hf_ip_tos_precedence = -1;
75 static int hf_ip_tos_delay = -1;
76 static int hf_ip_tos_throughput = -1;
77 static int hf_ip_tos_reliability = -1;
78 static int hf_ip_tos_cost = -1;
79 static int hf_ip_len = -1;
80 static int hf_ip_id = -1;
81 static int hf_ip_dst = -1;
82 static int hf_ip_src = -1;
83 static int hf_ip_addr = -1;
84 static int hf_ip_flags = -1;
85 static int hf_ip_flags_df = -1;
86 static int hf_ip_flags_mf = -1;
87 static int hf_ip_frag_offset = -1;
88 static int hf_ip_ttl = -1;
89 static int hf_ip_proto = -1;
90 static int hf_ip_checksum = -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;
118 static gint ett_icmp = -1;
120 /* ICMP structs and definitions */
121 typedef struct _e_icmp {
126 struct { /* Address mask request/reply */
131 struct { /* Timestap request/reply */
138 guint32 zero; /* Unreachable */
142 #define ICMP_ECHOREPLY 0
143 #define ICMP_UNREACH 3
144 #define ICMP_SOURCEQUENCH 4
145 #define ICMP_REDIRECT 5
147 #define ICMP_RTRADVERT 9
148 #define ICMP_RTRSOLICIT 10
149 #define ICMP_TIMXCEED 11
150 #define ICMP_PARAMPROB 12
151 #define ICMP_TSTAMP 13
152 #define ICMP_TSTAMPREPLY 14
154 #define ICMP_IREQREPLY 16
155 #define ICMP_MASKREQ 17
156 #define ICMP_MASKREPLY 18
158 /* ICMP UNREACHABLE */
160 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
161 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
162 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
163 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
164 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
165 #define ICMP_SR_FAILED 5 /* Source Route failed */
166 #define ICMP_NET_UNKNOWN 6
167 #define ICMP_HOST_UNKNOWN 7
168 #define ICMP_HOST_ISOLATED 8
169 #define ICMP_NET_ANO 9
170 #define ICMP_HOST_ANO 10
171 #define ICMP_NET_UNR_TOS 11
172 #define ICMP_HOST_UNR_TOS 12
173 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
174 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
175 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
178 /* IGMP structs and definitions */
179 typedef struct _e_igmp {
180 guint8 igmp_v_t; /* combines igmp_v and igmp_t */
186 #define IGMP_M_QRY 0x01
187 #define IGMP_V1_M_RPT 0x02
188 #define IGMP_V2_LV_GRP 0x07
189 #define IGMP_DVMRP 0x03
190 #define IGMP_PIM 0x04
191 #define IGMP_V2_M_RPT 0x06
192 #define IGMP_MTRC_RESP 0x1e
193 #define IGMP_MTRC 0x1f
195 /* EIGRP Structs and Definitions. */
199 #define EIGRP_UPDATE 0x01
200 #define EIGRP_REQUEST 0x02
201 #define EIGRP_QUERY 0x03
202 #define EIGRP_REPLY 0x04
203 #define EIGRP_HELLO 0x05
205 typedef struct _e_eigrp
207 guint8 eigrp_version;
209 guint16 eigrp_checksum;
210 guint16 eigrp_subnets;
211 guint16 eigrp_networks;
212 guint32 eigrp_sequence;
213 guint32 eigrp_asnumber;
215 guint8 eigrp_subtype1;
216 guint16 eigrp_length1;
217 guint16 eigrp_holdtime;
219 guint8 eigrp_subtype2;
220 guint16 eigrp_length2;
225 /* IP structs and definitions */
229 guint8 ip_v_hl; /* combines ip_v and ip_hl */
241 /* Offsets of fields within an IP header. */
253 /* Minimum IP header length. */
254 #define IPH_MIN_LEN 20
257 #define IP_CE 0x8000 /* Flag: "Congestion" */
258 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
259 #define IP_MF 0x2000 /* Flag: "More Fragments" */
260 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
262 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
263 #define IPDSFIELD_DSCP_MASK 0xFC
264 #define IPDSFIELD_DSCP_SHIFT 2
265 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
266 #define IPDSFIELD_DSCP_DEFAULT 0x00
267 #define IPDSFIELD_DSCP_CS1 0x08
268 #define IPDSFIELD_DSCP_CS2 0x10
269 #define IPDSFIELD_DSCP_CS3 0x18
270 #define IPDSFIELD_DSCP_CS4 0x20
271 #define IPDSFIELD_DSCP_CS5 0x28
272 #define IPDSFIELD_DSCP_CS6 0x30
273 #define IPDSFIELD_DSCP_CS7 0x38
274 #define IPDSFIELD_DSCP_AF11 0x0A
275 #define IPDSFIELD_DSCP_AF12 0x0C
276 #define IPDSFIELD_DSCP_AF13 0x0E
277 #define IPDSFIELD_DSCP_AF21 0x12
278 #define IPDSFIELD_DSCP_AF22 0x14
279 #define IPDSFIELD_DSCP_AF23 0x16
280 #define IPDSFIELD_DSCP_AF31 0x1A
281 #define IPDSFIELD_DSCP_AF32 0x1C
282 #define IPDSFIELD_DSCP_AF33 0x1E
283 #define IPDSFIELD_DSCP_AF41 0x22
284 #define IPDSFIELD_DSCP_AF42 0x24
285 #define IPDSFIELD_DSCP_AF43 0x26
286 #define IPDSFIELD_DSCP_EF 0x2E
287 #define IPDSFIELD_CU_MASK 0x03
289 /* IP TOS, superseded by the DS Field, RFC 2474. */
290 #define IPTOS_TOS_MASK 0x1E
291 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
292 #define IPTOS_NONE 0x00
293 #define IPTOS_LOWCOST 0x02
294 #define IPTOS_RELIABILITY 0x04
295 #define IPTOS_THROUGHPUT 0x08
296 #define IPTOS_LOWDELAY 0x10
297 #define IPTOS_SECURITY 0x1E
299 #define IPTOS_PREC_MASK 0xE0
300 #define IPTOS_PREC_SHIFT 5
301 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
302 #define IPTOS_PREC_NETCONTROL 7
303 #define IPTOS_PREC_INTERNETCONTROL 6
304 #define IPTOS_PREC_CRITIC_ECP 5
305 #define IPTOS_PREC_FLASHOVERRIDE 4
306 #define IPTOS_PREC_FLASH 3
307 #define IPTOS_PREC_IMMEDIATE 2
308 #define IPTOS_PREC_PRIORITY 1
309 #define IPTOS_PREC_ROUTINE 0
312 #define IPOPT_COPY 0x80
314 #define IPOPT_CONTROL 0x00
315 #define IPOPT_RESERVED1 0x20
316 #define IPOPT_MEASUREMENT 0x40
317 #define IPOPT_RESERVED2 0x60
319 #define IPOPT_END (0 |IPOPT_CONTROL)
320 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
321 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
322 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
323 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
324 #define IPOPT_RR (7 |IPOPT_CONTROL)
325 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
326 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
327 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
329 /* IP option lengths */
330 #define IPOLEN_SEC 11
331 #define IPOLEN_LSRR_MIN 3
332 #define IPOLEN_TIMESTAMP_MIN 5
333 #define IPOLEN_RR_MIN 3
335 #define IPOLEN_SSRR_MIN 3
337 #define IPSEC_UNCLASSIFIED 0x0000
338 #define IPSEC_CONFIDENTIAL 0xF135
339 #define IPSEC_EFTO 0x789A
340 #define IPSEC_MMMM 0xBC4D
341 #define IPSEC_RESTRICTED 0xAF13
342 #define IPSEC_SECRET 0xD788
343 #define IPSEC_TOPSECRET 0x6BC5
344 #define IPSEC_RESERVED1 0x35E2
345 #define IPSEC_RESERVED2 0x9AF1
346 #define IPSEC_RESERVED3 0x4D78
347 #define IPSEC_RESERVED4 0x24BD
348 #define IPSEC_RESERVED5 0x135E
349 #define IPSEC_RESERVED6 0x89AF
350 #define IPSEC_RESERVED7 0xC4D6
351 #define IPSEC_RESERVED8 0xE26B
353 #define IPOPT_TS_TSONLY 0 /* timestamps only */
354 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
355 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
359 capture_ip(const u_char *pd, int offset, packet_counts *ld) {
360 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
364 switch (pd[offset + 9]) {
389 dissect_ipopt_security(const ip_tcp_opt *optp, const u_char *opd, int offset,
390 guint optlen, proto_tree *opt_tree)
392 proto_tree *field_tree = NULL;
395 static const value_string secl_vals[] = {
396 {IPSEC_UNCLASSIFIED, "Unclassified"},
397 {IPSEC_CONFIDENTIAL, "Confidential"},
398 {IPSEC_EFTO, "EFTO" },
399 {IPSEC_MMMM, "MMMM" },
400 {IPSEC_RESTRICTED, "Restricted" },
401 {IPSEC_SECRET, "Secret" },
402 {IPSEC_TOPSECRET, "Top secret" },
403 {IPSEC_RESERVED1, "Reserved" },
404 {IPSEC_RESERVED2, "Reserved" },
405 {IPSEC_RESERVED3, "Reserved" },
406 {IPSEC_RESERVED4, "Reserved" },
407 {IPSEC_RESERVED5, "Reserved" },
408 {IPSEC_RESERVED6, "Reserved" },
409 {IPSEC_RESERVED7, "Reserved" },
410 {IPSEC_RESERVED8, "Reserved" },
413 tf = proto_tree_add_text(opt_tree, NullTVB, offset, optlen, "%s:", optp->name);
414 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
418 proto_tree_add_text(field_tree, NullTVB, offset, 2,
419 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
424 proto_tree_add_text(field_tree, NullTVB, offset, 2,
425 "Compartments: %u", val);
429 proto_tree_add_text(field_tree, NullTVB, offset, 2,
430 "Handling restrictions: %c%c", opd[0], opd[1]);
434 proto_tree_add_text(field_tree, NullTVB, offset, 3,
435 "Transmission control code: %c%c%c", opd[0], opd[1], opd[2]);
439 dissect_ipopt_route(const ip_tcp_opt *optp, const u_char *opd, int offset,
440 guint optlen, proto_tree *opt_tree)
442 proto_tree *field_tree = NULL;
448 tf = proto_tree_add_text(opt_tree, NullTVB, offset, optlen, "%s (%u bytes)",
450 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
452 optoffset += 2; /* skip past type and length */
453 optlen -= 2; /* subtract size of type and length */
456 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
457 "Pointer: %d%s", ptr,
458 ((ptr < 4) ? " (points before first address)" :
459 ((ptr & 3) ? " (points to middle of address)" : "")));
463 ptr--; /* ptr is 1-origin */
467 proto_tree_add_text(field_tree, NullTVB, offset, optlen,
468 "(suboption would go past end of option)");
472 /* Avoids alignment problems on many architectures. */
473 memcpy((char *)&addr, (char *)opd, sizeof(addr));
475 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 4,
477 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
478 ((optoffset == ptr) ? " <- (current)" : ""));
486 dissect_ipopt_sid(const ip_tcp_opt *optp, const u_char *opd, int offset,
487 guint optlen, proto_tree *opt_tree)
489 proto_tree_add_text(opt_tree, NullTVB, offset, optlen,
490 "%s: %d", optp->name, pntohs(opd));
495 dissect_ipopt_timestamp(const ip_tcp_opt *optp, const u_char *opd,
496 int offset, guint optlen, proto_tree *opt_tree)
498 proto_tree *field_tree = NULL;
503 static const value_string flag_vals[] = {
504 {IPOPT_TS_TSONLY, "Time stamps only" },
505 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
506 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
511 tf = proto_tree_add_text(opt_tree, NullTVB, offset, optlen, "%s:", optp->name);
512 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
514 optoffset += 2; /* skip past type and length */
515 optlen -= 2; /* subtract size of type and length */
518 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
519 "Pointer: %d%s", ptr,
520 ((ptr < 5) ? " (points before first address)" :
521 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
525 ptr--; /* ptr is 1-origin */
528 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
529 "Overflow: %d", flg >> 4);
531 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
532 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
538 if (flg == IPOPT_TS_TSANDADDR) {
539 /* XXX - check whether it goes past end of packet */
541 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, optlen,
542 "(suboption would go past end of option)");
545 memcpy((char *)&addr, (char *)opd, sizeof(addr));
550 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 8,
551 "Address = %s, time stamp = %u",
552 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
557 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, optlen,
558 "(suboption would go past end of option)");
561 /* XXX - check whether it goes past end of packet */
565 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 4,
566 "Time stamp = %u", ts);
572 static const ip_tcp_opt ipopts[] = {
595 dissect_ipopt_security
599 "Strict source route",
600 &ett_ip_option_route,
607 "Loose source route",
608 &ett_ip_option_route,
616 &ett_ip_option_route,
632 &ett_ip_option_timestamp,
634 IPOLEN_TIMESTAMP_MIN,
635 dissect_ipopt_timestamp
639 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
641 /* Dissect the IP or TCP options in a packet. */
643 dissect_ip_tcp_options(const u_char *opd, int offset, guint length,
644 const ip_tcp_opt *opttab, int nopts, int eol,
645 proto_tree *opt_tree)
648 const ip_tcp_opt *optp;
649 opt_len_type len_type;
652 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
653 void (*dissect)(const struct ip_tcp_opt *, const u_char *,
654 int, guint, proto_tree *);
659 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
660 if (optp->optcode == opt)
663 if (optp == &opttab[nopts]) {
664 /* We assume that the only NO_LENGTH options are EOL and NOP options,
665 so that we can treat unknown options as VARIABLE_LENGTH with a
666 minimum of 2, and at least be able to move on to the next option
667 by using the length in the option. */
668 optp = NULL; /* indicate that we don't know this option */
669 len_type = VARIABLE_LENGTH;
671 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
675 len_type = optp->len_type;
676 optlen = optp->optlen;
678 dissect = optp->dissect;
680 --length; /* account for type byte */
681 if (len_type != NO_LENGTH) {
682 /* Option has a length. Is it in the packet? */
684 /* Bogus - packet must at least include option code byte and
686 proto_tree_add_text(opt_tree, NullTVB, offset, 1,
687 "%s (length byte past end of options)", name);
690 len = *opd++; /* total including type, len */
691 --length; /* account for length byte */
693 /* Bogus - option length is too short to include option code and
695 proto_tree_add_text(opt_tree, NullTVB, offset, 2,
696 "%s (with too-short option length = %u byte%s)", name,
697 len, plurality(len, "", "s"));
699 } else if (len - 2 > length) {
700 /* Bogus - option goes past the end of the header. */
701 proto_tree_add_text(opt_tree, NullTVB, offset, length,
702 "%s (option length = %u byte%s says option goes past end of options)",
703 name, len, plurality(len, "", "s"));
705 } else if (len_type == FIXED_LENGTH && len != optlen) {
706 /* Bogus - option length isn't what it's supposed to be for this
708 proto_tree_add_text(opt_tree, NullTVB, offset, len,
709 "%s (with option length = %u byte%s; should be %u)", name,
710 len, plurality(len, "", "s"), optlen);
712 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
713 /* Bogus - option length is less than what it's supposed to be for
715 proto_tree_add_text(opt_tree, NullTVB, offset, len,
716 "%s (with option length = %u byte%s; should be >= %u)", name,
717 len, plurality(len, "", "s"), optlen);
721 proto_tree_add_text(opt_tree, NullTVB, offset, len, "%s (%u byte%s)",
722 name, len, plurality(len, "", "s"));
724 if (dissect != NULL) {
725 /* Option has a dissector. */
726 (*dissect)(optp, opd, offset, len, opt_tree);
728 /* Option has no data, hence no dissector. */
729 proto_tree_add_text(opt_tree, NullTVB, offset, len, "%s", name);
732 len -= 2; /* subtract size of type and length */
738 proto_tree_add_text(opt_tree, NullTVB, offset, 1, "%s", name);
746 static const value_string dscp_vals[] = {
747 { IPDSFIELD_DSCP_DEFAULT, "Default" },
748 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
749 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
750 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
751 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
752 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
753 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
754 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
755 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
756 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
757 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
758 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
759 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
760 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
761 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
762 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
763 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
764 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
765 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
766 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
767 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
770 static const value_string precedence_vals[] = {
771 { IPTOS_PREC_ROUTINE, "routine" },
772 { IPTOS_PREC_PRIORITY, "priority" },
773 { IPTOS_PREC_IMMEDIATE, "immediate" },
774 { IPTOS_PREC_FLASH, "flash" },
775 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
776 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
777 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
778 { IPTOS_PREC_NETCONTROL, "network control" },
781 static const value_string iptos_vals[] = {
782 { IPTOS_NONE, "None" },
783 { IPTOS_LOWCOST, "Minimize cost" },
784 { IPTOS_RELIABILITY, "Maximize reliability" },
785 { IPTOS_THROUGHPUT, "Maximize throughput" },
786 { IPTOS_LOWDELAY, "Minimize delay" },
787 { IPTOS_SECURITY, "Maximize security" },
791 static const true_false_string tos_set_low = {
796 static const true_false_string tos_set_high = {
801 static const true_false_string flags_set_truth = {
806 static char *ip_checksum_state(e_ip *iph)
809 unsigned char *Ptr, *PtrEnd;
813 PtrEnd = (lo_nibble(iph->ip_v_hl) * 4 + (char *)iph);
814 for (Ptr = (unsigned char *) iph; Ptr < PtrEnd; Ptr += 2) {
815 memcpy(&word, Ptr, sizeof word);
819 Sum = (Sum & 0xFFFF) + (Sum >> 16);
820 Sum = (Sum & 0xFFFF) + (Sum >> 16);
829 dissect_ip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
831 proto_tree *ip_tree, *field_tree;
834 guint hlen, optlen, len;
839 /* To do: check for errs, etc. */
840 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
841 dissect_data(pd, offset, fd, tree);
845 /* Avoids alignment problems on many architectures. */
846 memcpy(&iph, &pd[offset], sizeof(e_ip));
847 iph.ip_len = ntohs(iph.ip_len);
848 iph.ip_id = ntohs(iph.ip_id);
849 iph.ip_off = ntohs(iph.ip_off);
850 iph.ip_sum = ntohs(iph.ip_sum);
852 /* Length of IP datagram plus headers above it. */
853 len = iph.ip_len + offset;
855 /* Set the payload and captured-payload lengths to the minima of (the
856 IP length plus the length of the headers above it) and the frame
860 if (pi.captured_len > len)
861 pi.captured_len = len;
863 /* XXX - check to make sure this is at least IPH_MIN_LEN. */
864 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
868 switch (IPTOS_TOS(iph.ip_tos)) {
870 strcpy(tos_str, "None");
873 strcpy(tos_str, "Minimize cost");
875 case IPTOS_RELIABILITY:
876 strcpy(tos_str, "Maximize reliability");
878 case IPTOS_THROUGHPUT:
879 strcpy(tos_str, "Maximize throughput");
882 strcpy(tos_str, "Minimize delay");
885 strcpy(tos_str, "Maximize security");
888 strcpy(tos_str, "Unknown. Malformed?");
892 ti = proto_tree_add_item(tree, proto_ip, NullTVB, offset, hlen, NULL);
893 ip_tree = proto_item_add_subtree(ti, ett_ip);
895 proto_tree_add_item(ip_tree, hf_ip_version, NullTVB, offset, 1, hi_nibble(iph.ip_v_hl));
896 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, NullTVB, offset, 1, hlen,
897 "Header length: %u bytes", hlen);
899 if (g_ip_dscp_actif) {
900 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, NullTVB, offset + 1, 1, iph.ip_tos,
901 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s)", iph.ip_tos,
902 IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
905 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
906 proto_tree_add_item(field_tree, hf_ip_dsfield_dscp, NullTVB, offset + 1, 1, iph.ip_tos);
907 proto_tree_add_item(field_tree, hf_ip_dsfield_cu, NullTVB, offset + 1, 1, iph.ip_tos);
909 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, NullTVB, offset + 1, 1, iph.ip_tos,
910 "Type of service: 0x%02x (%s)", iph.ip_tos,
911 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
913 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
914 proto_tree_add_item(field_tree, hf_ip_tos_precedence, NullTVB, offset + 1, 1, iph.ip_tos);
915 proto_tree_add_item(field_tree, hf_ip_tos_delay, NullTVB, offset + 1, 1, iph.ip_tos);
916 proto_tree_add_item(field_tree, hf_ip_tos_throughput, NullTVB, offset + 1, 1, iph.ip_tos);
917 proto_tree_add_item(field_tree, hf_ip_tos_reliability, NullTVB, offset + 1, 1, iph.ip_tos);
918 proto_tree_add_item(field_tree, hf_ip_tos_cost, NullTVB, offset + 1, 1, iph.ip_tos);
920 proto_tree_add_item(ip_tree, hf_ip_len, NullTVB, offset + 2, 2, iph.ip_len);
921 proto_tree_add_item(ip_tree, hf_ip_id, NullTVB, offset + 4, 2, iph.ip_id);
923 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
924 tf = proto_tree_add_item(ip_tree, hf_ip_flags, NullTVB, offset + 6, 1, flags);
925 field_tree = proto_item_add_subtree(tf, ett_ip_off);
926 proto_tree_add_item(field_tree, hf_ip_flags_df, NullTVB, offset + 6, 1, flags),
927 proto_tree_add_item(field_tree, hf_ip_flags_mf, NullTVB, offset + 6, 1, flags),
929 proto_tree_add_item(ip_tree, hf_ip_frag_offset, NullTVB, offset + 6, 2,
930 iph.ip_off & IP_OFFSET);
931 proto_tree_add_item(ip_tree, hf_ip_ttl, NullTVB, offset + 8, 1, iph.ip_ttl);
932 proto_tree_add_uint_format(ip_tree, hf_ip_proto, NullTVB, offset + 9, 1, iph.ip_p,
933 "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
934 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, NullTVB, offset + 10, 2, iph.ip_sum,
935 "Header checksum: 0x%04x (%s)", iph.ip_sum, ip_checksum_state((e_ip*) &pd[offset]));
936 proto_tree_add_item(ip_tree, hf_ip_src, NullTVB, offset + 12, 4, iph.ip_src);
937 proto_tree_add_item(ip_tree, hf_ip_dst, NullTVB, offset + 16, 4, iph.ip_dst);
938 proto_tree_add_item_hidden(ip_tree, hf_ip_addr, NullTVB, offset + 12, 4, iph.ip_src);
939 proto_tree_add_item_hidden(ip_tree, hf_ip_addr, NullTVB, offset + 16, 4, iph.ip_dst);
941 /* Decode IP options, if any. */
942 if (hlen > sizeof (e_ip)) {
943 /* There's more than just the fixed-length header. Decode the
945 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
946 tf = proto_tree_add_text(ip_tree, NullTVB, offset + 20, optlen,
947 "Options: (%u bytes)", optlen);
948 field_tree = proto_item_add_subtree(tf, ett_ip_options);
949 dissect_ip_tcp_options(&pd[offset + 20], offset + 20, optlen,
950 ipopts, N_IP_OPTS, IPOPT_END, field_tree);
954 pi.ipproto = iph.ip_p;
955 pi.iplen = iph.ip_len;
956 pi.iphdrlen = lo_nibble(iph.ip_v_hl);
957 SET_ADDRESS(&pi.net_src, AT_IPv4, 4, &pd[offset + IPH_SRC]);
958 SET_ADDRESS(&pi.src, AT_IPv4, 4, &pd[offset + IPH_SRC]);
959 SET_ADDRESS(&pi.net_dst, AT_IPv4, 4, &pd[offset + IPH_DST]);
960 SET_ADDRESS(&pi.dst, AT_IPv4, 4, &pd[offset + IPH_DST]);
962 /* Skip over header + options */
965 if (iph.ip_off & IP_OFFSET) {
967 if (check_col(fd, COL_PROTOCOL))
968 col_add_str(fd, COL_PROTOCOL, "IP");
969 if (check_col(fd, COL_INFO))
970 col_add_fstr(fd, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
971 ipprotostr(iph.ip_p), iph.ip_p, iph.ip_off & IP_OFFSET);
972 dissect_data(pd, offset, fd, tree);
979 advance = dissect_ah(pd, offset, fd, tree);
985 /* do lookup with the subdissector table */
986 if (!dissector_try_port(ip_dissector_table, nxt, pd, offset, fd, tree)) {
987 /* Unknown protocol */
988 if (check_col(fd, COL_PROTOCOL))
989 col_add_str(fd, COL_PROTOCOL, "IP");
990 if (check_col(fd, COL_INFO))
991 col_add_fstr(fd, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
992 dissect_data(pd, offset, fd, tree);
997 static const gchar *unreach_str[] = {"Network unreachable",
999 "Protocol unreachable",
1001 "Fragmentation needed",
1002 "Source route failed",
1003 "Destination network unknown",
1004 "Destination host unknown",
1005 "Source host isolated",
1006 "Network administratively prohibited",
1007 "Host administratively prohibited",
1008 "Network unreachable for TOS",
1009 "Host unreachable for TOS",
1010 "Communication administratively filtered",
1011 "Host precedence violation",
1012 "Precedence cutoff in effect"};
1014 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1016 static const gchar *redir_str[] = {"Redirect for network",
1017 "Redirect for host",
1018 "Redirect for TOS and network",
1019 "Redirect for TOS and host"};
1021 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1023 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
1024 "TTL equals 0 during reassembly"};
1026 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1028 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1030 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1033 dissect_icmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1035 proto_tree *icmp_tree;
1038 gchar type_str[64], code_str[64] = "";
1039 guint8 num_addrs = 0;
1040 guint8 addr_entry_size = 0;
1043 /* Avoids alignment problems on many architectures. */
1044 memcpy(&ih, &pd[offset], sizeof(e_icmp));
1045 /* To do: check for runts, errs, etc. */
1046 cksum = ntohs(ih.icmp_cksum);
1048 switch (ih.icmp_type) {
1049 case ICMP_ECHOREPLY:
1050 strcpy(type_str, "Echo (ping) reply");
1053 strcpy(type_str, "Destination unreachable");
1054 if (ih.icmp_code < N_UNREACH) {
1055 sprintf(code_str, "(%s)", unreach_str[ih.icmp_code]);
1057 strcpy(code_str, "(Unknown - error?)");
1060 case ICMP_SOURCEQUENCH:
1061 strcpy(type_str, "Source quench (flow control)");
1064 strcpy(type_str, "Redirect");
1065 if (ih.icmp_code < N_REDIRECT) {
1066 sprintf(code_str, "(%s)", redir_str[ih.icmp_code]);
1068 strcpy(code_str, "(Unknown - error?)");
1072 strcpy(type_str, "Echo (ping) request");
1074 case ICMP_RTRADVERT:
1075 strcpy(type_str, "Router advertisement");
1077 case ICMP_RTRSOLICIT:
1078 strcpy(type_str, "Router solicitation");
1081 strcpy(type_str, "Time-to-live exceeded");
1082 if (ih.icmp_code < N_TIMXCEED) {
1083 sprintf(code_str, "(%s)", ttl_str[ih.icmp_code]);
1085 strcpy(code_str, "(Unknown - error?)");
1088 case ICMP_PARAMPROB:
1089 strcpy(type_str, "Parameter problem");
1090 if (ih.icmp_code < N_PARAMPROB) {
1091 sprintf(code_str, "(%s)", par_str[ih.icmp_code]);
1093 strcpy(code_str, "(Unknown - error?)");
1097 strcpy(type_str, "Timestamp request");
1099 case ICMP_TSTAMPREPLY:
1100 strcpy(type_str, "Timestamp reply");
1103 strcpy(type_str, "Information request");
1105 case ICMP_IREQREPLY:
1106 strcpy(type_str, "Information reply");
1109 strcpy(type_str, "Address mask request");
1111 case ICMP_MASKREPLY:
1112 strcpy(type_str, "Address mask reply");
1115 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1118 if (check_col(fd, COL_PROTOCOL))
1119 col_add_str(fd, COL_PROTOCOL, "ICMP");
1120 if (check_col(fd, COL_INFO))
1121 col_add_str(fd, COL_INFO, type_str);
1124 ti = proto_tree_add_item(tree, proto_icmp, NullTVB, offset, 4, NULL);
1125 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1126 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, NullTVB, offset, 1,
1129 ih.icmp_type, type_str);
1130 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, NullTVB, offset + 1, 1,
1133 ih.icmp_code, code_str);
1134 proto_tree_add_item(icmp_tree, hf_icmp_checksum, NullTVB, offset + 2, 2,
1137 /* Decode the second 4 bytes of the packet. */
1138 switch (ih.icmp_type) {
1139 case ICMP_ECHOREPLY:
1142 case ICMP_TSTAMPREPLY:
1144 case ICMP_IREQREPLY:
1146 case ICMP_MASKREPLY:
1147 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 2, "Identifier: 0x%04x",
1148 pntohs(&pd[offset + 4]));
1149 proto_tree_add_text(icmp_tree, NullTVB, offset + 6, 2, "Sequence number: %u",
1150 pntohs(&pd[offset + 6]));
1154 switch (ih.icmp_code) {
1155 case ICMP_FRAG_NEEDED:
1156 proto_tree_add_text(icmp_tree, NullTVB, offset + 6, 2, "MTU of next hop: %u",
1157 pntohs(&pd[offset + 6]));
1162 case ICMP_RTRADVERT:
1163 num_addrs = pd[offset + 4];
1164 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 1, "Number of addresses: %u",
1166 addr_entry_size = pd[offset + 5];
1167 proto_tree_add_text(icmp_tree, NullTVB, offset + 5, 1, "Address entry size: %u",
1169 proto_tree_add_text(icmp_tree, NullTVB, offset + 6, 2, "Lifetime: %s",
1170 time_secs_to_str(pntohs(&pd[offset + 6])));
1173 case ICMP_PARAMPROB:
1174 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 1, "Pointer: %u",
1179 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 4, "Gateway address: %s",
1180 ip_to_str((guint8 *)&pd[offset + 4]));
1184 /* Decode the additional information in the packet. */
1185 switch (ih.icmp_type) {
1188 case ICMP_PARAMPROB:
1189 case ICMP_SOURCEQUENCH:
1191 /* Decode the IP header and first 64 bits of data from the
1194 XXX - for now, just display it as data; not all dissection
1195 routines can handle a short packet without exploding. */
1196 dissect_data(pd, offset + 8, fd, icmp_tree);
1199 case ICMP_ECHOREPLY:
1201 dissect_data(pd, offset + 8, fd, icmp_tree);
1204 case ICMP_RTRADVERT:
1205 if (addr_entry_size == 2) {
1206 for (i = 0; i < num_addrs; i++) {
1207 proto_tree_add_text(icmp_tree, NullTVB, offset + 8 + (i*8), 4,
1208 "Router address: %s",
1209 ip_to_str((guint8 *)&pd[offset + 8 + (i*8)]));
1210 proto_tree_add_text(icmp_tree, NullTVB, offset + 12 + (i*8), 4,
1211 "Preference level: %u", pntohl(&pd[offset + 12 + (i*8)]));
1214 dissect_data(pd, offset + 8, fd, icmp_tree);
1218 case ICMP_TSTAMPREPLY:
1219 proto_tree_add_text(icmp_tree, NullTVB, offset + 8, 4, "Originate timestamp: %u",
1220 pntohl(&pd[offset + 8]));
1221 proto_tree_add_text(icmp_tree, NullTVB, offset + 12, 4, "Receive timestamp: %u",
1222 pntohl(&pd[offset + 12]));
1223 proto_tree_add_text(icmp_tree, NullTVB, offset + 16, 4, "Transmit timestamp: %u",
1224 pntohl(&pd[offset + 16]));
1228 case ICMP_MASKREPLY:
1229 proto_tree_add_text(icmp_tree, NullTVB, offset + 8, 4, "Address mask: %s (0x%8x)",
1230 ip_to_str((guint8 *)&pd[offset + 8]), pntohl(&pd[offset + 8]));
1237 dissect_igmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1239 proto_tree *igmp_tree;
1242 gchar type_str[64] = "";
1244 /* Avoids alignment problems on many architectures. */
1245 memcpy(&ih, &pd[offset], sizeof(e_igmp));
1246 /* To do: check for runts, errs, etc. */
1247 cksum = ntohs(ih.igmp_cksum);
1249 switch (lo_nibble(ih.igmp_v_t)) {
1251 strcpy(type_str, "Router query");
1254 strcpy(type_str, "Host response (v1)");
1256 case IGMP_V2_LV_GRP:
1257 strcpy(type_str, "Leave group (v2)");
1260 strcpy(type_str, "DVMRP");
1263 strcpy(type_str, "PIM");
1266 strcpy(type_str, "Host response (v2)");
1268 case IGMP_MTRC_RESP:
1269 strcpy(type_str, "Traceroute response");
1272 strcpy(type_str, "Traceroute message");
1275 strcpy(type_str, "Unknown IGMP");
1278 if (check_col(fd, COL_PROTOCOL))
1279 col_add_str(fd, COL_PROTOCOL, "IGMP");
1280 if (check_col(fd, COL_INFO))
1281 col_add_str(fd, COL_INFO, type_str);
1283 ti = proto_tree_add_item(tree, proto_igmp, NullTVB, offset, 8, NULL);
1284 igmp_tree = proto_item_add_subtree(ti, ett_igmp);
1285 proto_tree_add_item(igmp_tree, hf_igmp_version, NullTVB, offset, 1,
1286 hi_nibble(ih.igmp_v_t));
1287 proto_tree_add_uint_format(igmp_tree, hf_igmp_type, NullTVB, offset , 1,
1288 lo_nibble(ih.igmp_v_t),
1290 lo_nibble(ih.igmp_v_t), type_str);
1291 proto_tree_add_uint_format(igmp_tree, hf_igmp_unused, NullTVB, offset + 1, 1,
1295 proto_tree_add_item(igmp_tree, hf_igmp_checksum, NullTVB, offset + 2, 2,
1297 proto_tree_add_item(igmp_tree, hf_igmp_group, NullTVB, offset + 4, 4,
1303 proto_register_igmp(void)
1305 static hf_register_info hf[] = {
1308 { "Version", "igmp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1312 { "Type", "igmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1316 { "Unused", "igmp.unused", FT_UINT8, BASE_DEC, NULL, 0x0,
1319 { &hf_igmp_checksum,
1320 { "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1324 { "Group address", "igmp.group", FT_IPv4, BASE_NONE, NULL, 0x0,
1327 static gint *ett[] = {
1331 proto_igmp = proto_register_protocol ("Internet Group Management Protocol", "igmp");
1332 proto_register_field_array(proto_igmp, hf, array_length(hf));
1333 proto_register_subtree_array(ett, array_length(ett));
1337 proto_reg_handoff_igmp(void)
1339 dissector_add("ip.proto", IP_PROTO_IGMP, dissect_igmp);
1343 proto_register_ip(void)
1345 static hf_register_info hf[] = {
1348 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1352 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1356 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1359 { &hf_ip_dsfield_dscp,
1360 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1361 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1364 { &hf_ip_dsfield_cu,
1365 { "Currently Unused", "ip.dsfield.cu", 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,
1457 proto_ip = proto_register_protocol ("Internet Protocol", "ip");
1458 proto_register_field_array(proto_ip, hf, array_length(hf));
1459 proto_register_subtree_array(ett, array_length(ett));
1461 /* subdissector code */
1462 ip_dissector_table = register_dissector_table("ip.proto");
1466 proto_reg_handoff_ip(void)
1468 dissector_add("ethertype", ETHERTYPE_IP, dissect_ip);
1469 dissector_add("ppp.protocol", PPP_IP, dissect_ip);
1470 dissector_add("llc.dsap", SAP_IP, dissect_ip);
1471 dissector_add("ip.proto", IP_PROTO_IPV4, dissect_ip);
1472 dissector_add("ip.proto", IP_PROTO_IPIP, dissect_ip);
1476 proto_register_icmp(void)
1478 static hf_register_info hf[] = {
1481 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1485 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1488 { &hf_icmp_checksum,
1489 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1492 static gint *ett[] = {
1496 proto_icmp = proto_register_protocol ("Internet Control Message Protocol",
1498 proto_register_field_array(proto_icmp, hf, array_length(hf));
1499 proto_register_subtree_array(ett, array_length(ett));
1503 proto_reg_handoff_icmp(void)
1505 dissector_add("ip.proto", IP_PROTO_ICMP, dissect_icmp);
1508 static int proto_eigrp = -1;
1510 static gint ett_eigrp = -1;
1512 static const value_string eigrp_opcode_vals[] = {
1513 { EIGRP_HELLO, "Hello/Ack" },
1514 { EIGRP_UPDATE, "Update" },
1515 { EIGRP_REPLY, "Reply" },
1516 { EIGRP_QUERY, "Query" },
1517 { EIGRP_REQUEST, "Request" },
1522 dissect_eigrp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1524 proto_tree *eigrp_tree;
1528 /* Avoids alignment problems on many architectures. */
1529 memcpy(&ih, &pd[offset], sizeof(e_eigrp));
1530 /* To do: check for runts, errs, etc. */
1531 cksum = ntohs(ih.eigrp_checksum);
1533 if (check_col(fd, COL_PROTOCOL))
1534 col_add_str(fd, COL_PROTOCOL, "EIGRP");
1535 if (check_col(fd, COL_INFO))
1536 col_add_str(fd, COL_INFO,
1537 val_to_str( ih.eigrp_opcode, eigrp_opcode_vals, "Unknown (0x%04x)"));
1540 ti = proto_tree_add_item(tree, proto_eigrp, NullTVB, offset, END_OF_FRAME, NULL);
1541 eigrp_tree = proto_item_add_subtree(ti, ett_eigrp);
1543 proto_tree_add_text(eigrp_tree, NullTVB, offset, 1, "Version: %u", ih.eigrp_version);
1544 proto_tree_add_text(eigrp_tree, NullTVB, offset + 1, 1, "Opcode: %u (%s)", ih.eigrp_opcode,
1545 val_to_str( ih.eigrp_opcode, eigrp_opcode_vals, "Unknown") );
1546 proto_tree_add_text(eigrp_tree, NullTVB, offset + 2, 2, "Checksum: 0x%x", cksum);
1547 proto_tree_add_text(eigrp_tree, NullTVB, offset + 4, 2, "Subnets in local net: %u", ih.eigrp_subnets);
1548 proto_tree_add_text(eigrp_tree, NullTVB, offset + 6, 2, "Networks in Autonomous System: %d", ih.eigrp_networks);
1549 proto_tree_add_text(eigrp_tree, NullTVB, offset + 8, 4, "Sequence Number: 0x%x", ih.eigrp_sequence);
1550 proto_tree_add_text(eigrp_tree, NullTVB, offset + 12, 4, "Autonomous System number: %u", ih.eigrp_asnumber);
1556 proto_register_eigrp(void)
1558 static gint *ett[] = {
1561 proto_eigrp = proto_register_protocol("Enhanced Interior Gateway Routing Protocol", "eigrp");
1562 proto_register_subtree_array(ett, array_length(ett));
1566 proto_reg_handoff_eigrp(void)
1568 dissector_add("ip.proto", IP_PROTO_EIGRP, dissect_eigrp);