2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.73 2000/02/09 19:17:51 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"
53 #ifndef __PACKET_IP_H__
54 #include "packet-ip.h"
57 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
58 gboolean g_ip_dscp_actif = TRUE;
60 static int proto_ip = -1;
61 static int hf_ip_version = -1;
62 static int hf_ip_hdr_len = -1;
63 static int hf_ip_dsfield = -1;
64 static int hf_ip_dsfield_dscp = -1;
65 static int hf_ip_dsfield_cu = -1;
66 static int hf_ip_tos = -1;
67 static int hf_ip_tos_precedence = -1;
68 static int hf_ip_tos_delay = -1;
69 static int hf_ip_tos_throughput = -1;
70 static int hf_ip_tos_reliability = -1;
71 static int hf_ip_tos_cost = -1;
72 static int hf_ip_len = -1;
73 static int hf_ip_id = -1;
74 static int hf_ip_dst = -1;
75 static int hf_ip_src = -1;
76 static int hf_ip_addr = -1;
77 static int hf_ip_flags = -1;
78 static int hf_ip_flags_df = -1;
79 static int hf_ip_flags_mf = -1;
80 static int hf_ip_frag_offset = -1;
81 static int hf_ip_ttl = -1;
82 static int hf_ip_proto = -1;
83 static int hf_ip_checksum = -1;
85 static gint ett_ip = -1;
86 static gint ett_ip_dsfield = -1;
87 static gint ett_ip_tos = -1;
88 static gint ett_ip_off = -1;
89 static gint ett_ip_options = -1;
90 static gint ett_ip_option_sec = -1;
91 static gint ett_ip_option_route = -1;
92 static gint ett_ip_option_timestamp = -1;
94 static int proto_igmp = -1;
95 static int hf_igmp_version = -1;
96 static int hf_igmp_type = -1;
97 static int hf_igmp_unused = -1;
98 static int hf_igmp_checksum = -1;
99 static int hf_igmp_group = -1;
101 static gint ett_igmp = -1;
103 static int proto_icmp = -1;
104 static int hf_icmp_type = -1;
105 static int hf_icmp_code = -1;
106 static int hf_icmp_checksum = -1;
108 static gint ett_icmp = -1;
110 /* ICMP structs and definitions */
111 typedef struct _e_icmp {
116 struct { /* Address mask request/reply */
121 struct { /* Timestap request/reply */
128 guint32 zero; /* Unreachable */
132 #define ICMP_ECHOREPLY 0
133 #define ICMP_UNREACH 3
134 #define ICMP_SOURCEQUENCH 4
135 #define ICMP_REDIRECT 5
137 #define ICMP_RTRADVERT 9
138 #define ICMP_RTRSOLICIT 10
139 #define ICMP_TIMXCEED 11
140 #define ICMP_PARAMPROB 12
141 #define ICMP_TSTAMP 13
142 #define ICMP_TSTAMPREPLY 14
144 #define ICMP_IREQREPLY 16
145 #define ICMP_MASKREQ 17
146 #define ICMP_MASKREPLY 18
148 /* ICMP UNREACHABLE */
150 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
151 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
152 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
153 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
154 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
155 #define ICMP_SR_FAILED 5 /* Source Route failed */
156 #define ICMP_NET_UNKNOWN 6
157 #define ICMP_HOST_UNKNOWN 7
158 #define ICMP_HOST_ISOLATED 8
159 #define ICMP_NET_ANO 9
160 #define ICMP_HOST_ANO 10
161 #define ICMP_NET_UNR_TOS 11
162 #define ICMP_HOST_UNR_TOS 12
163 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
164 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
165 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
168 /* IGMP structs and definitions */
169 typedef struct _e_igmp {
170 guint8 igmp_v_t; /* combines igmp_v and igmp_t */
176 #define IGMP_M_QRY 0x01
177 #define IGMP_V1_M_RPT 0x02
178 #define IGMP_V2_LV_GRP 0x07
179 #define IGMP_DVMRP 0x03
180 #define IGMP_PIM 0x04
181 #define IGMP_V2_M_RPT 0x06
182 #define IGMP_MTRC_RESP 0x1e
183 #define IGMP_MTRC 0x1f
185 /* EIGRP Structs and Definitions. */
189 #define EIGRP_UPDATE 0x01
190 #define EIGRP_REQUEST 0x02
191 #define EIGRP_QUERY 0x03
192 #define EIGRP_REPLY 0x04
193 #define EIGRP_HELLO 0x05
195 typedef struct _e_eigrp
197 guint8 eigrp_version;
199 guint16 eigrp_checksum;
200 guint16 eigrp_subnets;
201 guint16 eigrp_networks;
202 guint32 eigrp_sequence;
203 guint32 eigrp_asnumber;
205 guint8 eigrp_subtype1;
206 guint16 eigrp_length1;
207 guint16 eigrp_holdtime;
209 guint8 eigrp_subtype2;
210 guint16 eigrp_length2;
215 /* IP structs and definitions */
219 guint8 ip_v_hl; /* combines ip_v and ip_hl */
231 /* Offsets of fields within an IP header. */
243 /* Minimum IP header length. */
244 #define IPH_MIN_LEN 20
247 #define IP_CE 0x8000 /* Flag: "Congestion" */
248 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
249 #define IP_MF 0x2000 /* Flag: "More Fragments" */
250 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
252 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
253 #define IPDSFIELD_DSCP_MASK 0xFC
254 #define IPDSFIELD_DSCP_SHIFT 2
255 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
256 #define IPDSFIELD_DSCP_DEFAULT 0x00
257 #define IPDSFIELD_DSCP_CS1 0x08
258 #define IPDSFIELD_DSCP_CS2 0x10
259 #define IPDSFIELD_DSCP_CS3 0x18
260 #define IPDSFIELD_DSCP_CS4 0x20
261 #define IPDSFIELD_DSCP_CS5 0x28
262 #define IPDSFIELD_DSCP_CS6 0x30
263 #define IPDSFIELD_DSCP_CS7 0x38
264 #define IPDSFIELD_DSCP_AF11 0x0A
265 #define IPDSFIELD_DSCP_AF12 0x0C
266 #define IPDSFIELD_DSCP_AF13 0x0E
267 #define IPDSFIELD_DSCP_AF21 0x12
268 #define IPDSFIELD_DSCP_AF22 0x14
269 #define IPDSFIELD_DSCP_AF23 0x16
270 #define IPDSFIELD_DSCP_AF31 0x1A
271 #define IPDSFIELD_DSCP_AF32 0x1C
272 #define IPDSFIELD_DSCP_AF33 0x1E
273 #define IPDSFIELD_DSCP_AF41 0x22
274 #define IPDSFIELD_DSCP_AF42 0x24
275 #define IPDSFIELD_DSCP_AF43 0x26
276 #define IPDSFIELD_DSCP_EF 0x2E
277 #define IPDSFIELD_CU_MASK 0x03
279 /* IP TOS, superseded by the DS Field, RFC 2474. */
280 #define IPTOS_TOS_MASK 0x1E
281 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
282 #define IPTOS_NONE 0x00
283 #define IPTOS_LOWCOST 0x02
284 #define IPTOS_RELIABILITY 0x04
285 #define IPTOS_THROUGHPUT 0x08
286 #define IPTOS_LOWDELAY 0x10
287 #define IPTOS_SECURITY 0x1E
289 #define IPTOS_PREC_MASK 0xE0
290 #define IPTOS_PREC_SHIFT 5
291 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
292 #define IPTOS_PREC_NETCONTROL 7
293 #define IPTOS_PREC_INTERNETCONTROL 6
294 #define IPTOS_PREC_CRITIC_ECP 5
295 #define IPTOS_PREC_FLASHOVERRIDE 4
296 #define IPTOS_PREC_FLASH 3
297 #define IPTOS_PREC_IMMEDIATE 2
298 #define IPTOS_PREC_PRIORITY 1
299 #define IPTOS_PREC_ROUTINE 0
302 #define IPOPT_COPY 0x80
304 #define IPOPT_CONTROL 0x00
305 #define IPOPT_RESERVED1 0x20
306 #define IPOPT_MEASUREMENT 0x40
307 #define IPOPT_RESERVED2 0x60
309 #define IPOPT_END (0 |IPOPT_CONTROL)
310 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
311 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
312 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
313 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
314 #define IPOPT_RR (7 |IPOPT_CONTROL)
315 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
316 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
317 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
319 /* IP option lengths */
320 #define IPOLEN_SEC 11
321 #define IPOLEN_LSRR_MIN 3
322 #define IPOLEN_TIMESTAMP_MIN 5
323 #define IPOLEN_RR_MIN 3
325 #define IPOLEN_SSRR_MIN 3
327 #define IPSEC_UNCLASSIFIED 0x0000
328 #define IPSEC_CONFIDENTIAL 0xF135
329 #define IPSEC_EFTO 0x789A
330 #define IPSEC_MMMM 0xBC4D
331 #define IPSEC_RESTRICTED 0xAF13
332 #define IPSEC_SECRET 0xD788
333 #define IPSEC_TOPSECRET 0x6BC5
334 #define IPSEC_RESERVED1 0x35E2
335 #define IPSEC_RESERVED2 0x9AF1
336 #define IPSEC_RESERVED3 0x4D78
337 #define IPSEC_RESERVED4 0x24BD
338 #define IPSEC_RESERVED5 0x135E
339 #define IPSEC_RESERVED6 0x89AF
340 #define IPSEC_RESERVED7 0xC4D6
341 #define IPSEC_RESERVED8 0xE26B
343 #define IPOPT_TS_TSONLY 0 /* timestamps only */
344 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
345 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
349 capture_ip(const u_char *pd, int offset, packet_counts *ld) {
350 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
354 switch (pd[offset + 9]) {
379 dissect_ipopt_security(const ip_tcp_opt *optp, const u_char *opd, int offset,
380 guint optlen, proto_tree *opt_tree)
382 proto_tree *field_tree = NULL;
385 static const value_string secl_vals[] = {
386 {IPSEC_UNCLASSIFIED, "Unclassified"},
387 {IPSEC_CONFIDENTIAL, "Confidential"},
388 {IPSEC_EFTO, "EFTO" },
389 {IPSEC_MMMM, "MMMM" },
390 {IPSEC_RESTRICTED, "Restricted" },
391 {IPSEC_SECRET, "Secret" },
392 {IPSEC_TOPSECRET, "Top secret" },
393 {IPSEC_RESERVED1, "Reserved" },
394 {IPSEC_RESERVED2, "Reserved" },
395 {IPSEC_RESERVED3, "Reserved" },
396 {IPSEC_RESERVED4, "Reserved" },
397 {IPSEC_RESERVED5, "Reserved" },
398 {IPSEC_RESERVED6, "Reserved" },
399 {IPSEC_RESERVED7, "Reserved" },
400 {IPSEC_RESERVED8, "Reserved" },
403 tf = proto_tree_add_text(opt_tree, offset, optlen, "%s:", optp->name);
404 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
408 proto_tree_add_text(field_tree, offset, 2,
409 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
414 proto_tree_add_text(field_tree, offset, 2,
415 "Compartments: %d", val);
419 proto_tree_add_text(field_tree, offset, 2,
420 "Handling restrictions: %c%c", opd[0], opd[1]);
424 proto_tree_add_text(field_tree, offset, 3,
425 "Transmission control code: %c%c%c", opd[0], opd[1], opd[2]);
429 dissect_ipopt_route(const ip_tcp_opt *optp, const u_char *opd, int offset,
430 guint optlen, proto_tree *opt_tree)
432 proto_tree *field_tree = NULL;
438 tf = proto_tree_add_text(opt_tree, offset, optlen, "%s (%d bytes)",
440 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
442 optoffset += 2; /* skip past type and length */
443 optlen -= 2; /* subtract size of type and length */
446 proto_tree_add_text(field_tree, offset + optoffset, 1,
447 "Pointer: %d%s", ptr,
448 ((ptr < 4) ? " (points before first address)" :
449 ((ptr & 3) ? " (points to middle of address)" : "")));
453 ptr--; /* ptr is 1-origin */
457 proto_tree_add_text(field_tree, offset, optlen,
458 "(suboption would go past end of option)");
462 /* Avoids alignment problems on many architectures. */
463 memcpy((char *)&addr, (char *)opd, sizeof(addr));
465 proto_tree_add_text(field_tree, offset + optoffset, 4,
467 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
468 ((optoffset == ptr) ? " <- (current)" : ""));
476 dissect_ipopt_sid(const ip_tcp_opt *optp, const u_char *opd, int offset,
477 guint optlen, proto_tree *opt_tree)
479 proto_tree_add_text(opt_tree, offset, optlen,
480 "%s: %d", optp->name, pntohs(opd));
485 dissect_ipopt_timestamp(const ip_tcp_opt *optp, const u_char *opd,
486 int offset, guint optlen, proto_tree *opt_tree)
488 proto_tree *field_tree = NULL;
493 static const value_string flag_vals[] = {
494 {IPOPT_TS_TSONLY, "Time stamps only" },
495 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
496 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
501 tf = proto_tree_add_text(opt_tree, offset, optlen, "%s:", optp->name);
502 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
504 optoffset += 2; /* skip past type and length */
505 optlen -= 2; /* subtract size of type and length */
508 proto_tree_add_text(field_tree, offset + optoffset, 1,
509 "Pointer: %d%s", ptr,
510 ((ptr < 5) ? " (points before first address)" :
511 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
515 ptr--; /* ptr is 1-origin */
518 proto_tree_add_text(field_tree, offset + optoffset, 1,
519 "Overflow: %d", flg >> 4);
521 proto_tree_add_text(field_tree, offset + optoffset, 1,
522 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
528 if (flg == IPOPT_TS_TSANDADDR) {
529 /* XXX - check whether it goes past end of packet */
531 proto_tree_add_text(field_tree, offset + optoffset, optlen,
532 "(suboption would go past end of option)");
535 memcpy((char *)&addr, (char *)opd, sizeof(addr));
540 proto_tree_add_text(field_tree, offset + optoffset, 8,
541 "Address = %s, time stamp = %u",
542 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
547 proto_tree_add_text(field_tree, offset + optoffset, optlen,
548 "(suboption would go past end of option)");
551 /* XXX - check whether it goes past end of packet */
555 proto_tree_add_text(field_tree, offset + optoffset, 4,
556 "Time stamp = %u", ts);
562 static const ip_tcp_opt ipopts[] = {
585 dissect_ipopt_security
589 "Strict source route",
590 &ett_ip_option_route,
597 "Loose source route",
598 &ett_ip_option_route,
606 &ett_ip_option_route,
622 &ett_ip_option_timestamp,
624 IPOLEN_TIMESTAMP_MIN,
625 dissect_ipopt_timestamp
629 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
631 /* Dissect the IP or TCP options in a packet. */
633 dissect_ip_tcp_options(const u_char *opd, int offset, guint length,
634 const ip_tcp_opt *opttab, int nopts, int eol,
635 proto_tree *opt_tree)
638 const ip_tcp_opt *optp;
639 opt_len_type len_type;
642 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
643 void (*dissect)(const struct ip_tcp_opt *, const u_char *,
644 int, guint, proto_tree *);
649 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
650 if (optp->optcode == opt)
653 if (optp == &opttab[nopts]) {
654 /* We assume that the only NO_LENGTH options are EOL and NOP options,
655 so that we can treat unknown options as VARIABLE_LENGTH with a
656 minimum of 2, and at least be able to move on to the next option
657 by using the length in the option. */
658 optp = NULL; /* indicate that we don't know this option */
659 len_type = VARIABLE_LENGTH;
661 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
665 len_type = optp->len_type;
666 optlen = optp->optlen;
668 dissect = optp->dissect;
670 --length; /* account for type byte */
671 if (len_type != NO_LENGTH) {
672 /* Option has a length. Is it in the packet? */
674 /* Bogus - packet must at least include option code byte and
676 proto_tree_add_text(opt_tree, offset, 1,
677 "%s (length byte past end of options)", name);
680 len = *opd++; /* total including type, len */
681 --length; /* account for length byte */
683 /* Bogus - option length is too short to include option code and
685 proto_tree_add_text(opt_tree, offset, 2,
686 "%s (with too-short option length = %u byte%s)", name,
687 len, plurality(len, "", "s"));
689 } else if (len - 2 > length) {
690 /* Bogus - option goes past the end of the header. */
691 proto_tree_add_text(opt_tree, offset, length,
692 "%s (option length = %u byte%s says option goes past end of options)",
693 name, len, plurality(len, "", "s"));
695 } else if (len_type == FIXED_LENGTH && len != optlen) {
696 /* Bogus - option length isn't what it's supposed to be for this
698 proto_tree_add_text(opt_tree, offset, len,
699 "%s (with option length = %u byte%s; should be %u)", name,
700 len, plurality(len, "", "s"), optlen);
702 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
703 /* Bogus - option length is less than what it's supposed to be for
705 proto_tree_add_text(opt_tree, offset, len,
706 "%s (with option length = %u byte%s; should be >= %u)", name,
707 len, plurality(len, "", "s"), optlen);
711 proto_tree_add_text(opt_tree, offset, len, "%s (%d byte%s)",
712 name, len, plurality(len, "", "s"));
714 if (dissect != NULL) {
715 /* Option has a dissector. */
716 (*dissect)(optp, opd, offset, len, opt_tree);
718 /* Option has no data, hence no dissector. */
719 proto_tree_add_text(opt_tree, offset, len, "%s", name);
722 len -= 2; /* subtract size of type and length */
728 proto_tree_add_text(opt_tree, offset, 1, "%s", name);
736 static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
737 {IP_PROTO_IGMP, "IGMP"},
738 {IP_PROTO_EIGRP, "IGRP/EIGRP"},
739 {IP_PROTO_TCP, "TCP" },
740 {IP_PROTO_UDP, "UDP" },
741 {IP_PROTO_OSPF, "OSPF"},
742 {IP_PROTO_RSVP, "RSVP"},
743 {IP_PROTO_AH, "AH" },
744 {IP_PROTO_GRE, "GRE" },
745 {IP_PROTO_ESP, "ESP" },
746 {IP_PROTO_IPV6, "IPv6"},
747 {IP_PROTO_PIM, "PIM" },
748 {IP_PROTO_VINES,"VINES"},
751 static const value_string dscp_vals[] = {
752 { IPDSFIELD_DSCP_DEFAULT, "Default" },
753 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
754 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
755 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
756 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
757 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
758 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
759 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
760 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
761 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
762 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
763 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
764 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
765 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
766 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
767 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
768 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
769 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
770 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
771 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
772 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
775 static const value_string precedence_vals[] = {
776 { IPTOS_PREC_ROUTINE, "routine" },
777 { IPTOS_PREC_PRIORITY, "priority" },
778 { IPTOS_PREC_IMMEDIATE, "immediate" },
779 { IPTOS_PREC_FLASH, "flash" },
780 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
781 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
782 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
783 { IPTOS_PREC_NETCONTROL, "network control" },
786 static const value_string iptos_vals[] = {
787 { IPTOS_NONE, "None" },
788 { IPTOS_LOWCOST, "Minimize cost" },
789 { IPTOS_RELIABILITY, "Maximize reliability" },
790 { IPTOS_THROUGHPUT, "Maximize throughput" },
791 { IPTOS_LOWDELAY, "Minimize delay" },
792 { IPTOS_SECURITY, "Maximize security" },
796 static const true_false_string tos_set_low = {
801 static const true_false_string tos_set_high = {
806 static const true_false_string flags_set_truth = {
811 static char *ip_checksum_state(e_ip *iph)
814 unsigned char *Ptr, *PtrEnd;
818 PtrEnd = (lo_nibble(iph->ip_v_hl) * 4 + (char *)iph);
819 for (Ptr = (unsigned char *) iph; Ptr < PtrEnd; Ptr += 2) {
820 memcpy(&word, Ptr, sizeof word);
824 Sum = (Sum & 0xFFFF) + (Sum >> 16);
825 Sum = (Sum & 0xFFFF) + (Sum >> 16);
834 dissect_ip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
836 proto_tree *ip_tree, *field_tree;
839 guint hlen, optlen, len;
844 /* To do: check for errs, etc. */
845 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
846 dissect_data(pd, offset, fd, tree);
850 /* Avoids alignment problems on many architectures. */
851 memcpy(&iph, &pd[offset], sizeof(e_ip));
852 iph.ip_len = ntohs(iph.ip_len);
853 iph.ip_id = ntohs(iph.ip_id);
854 iph.ip_off = ntohs(iph.ip_off);
855 iph.ip_sum = ntohs(iph.ip_sum);
857 /* Length of IP datagram plus headers above it. */
858 len = iph.ip_len + offset;
860 /* Set the payload and captured-payload lengths to the minima of (the
861 IP length plus the length of the headers above it) and the frame
865 if (pi.captured_len > len)
866 pi.captured_len = len;
868 /* XXX - check to make sure this is at least IPH_MIN_LEN. */
869 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
883 /* Names are set in the associated dissect_* routines */
886 if (check_col(fd, COL_PROTOCOL))
887 col_add_str(fd, COL_PROTOCOL, "IP");
888 if (check_col(fd, COL_INFO))
889 col_add_fstr(fd, COL_INFO, "%s (0x%02x)",
890 ipprotostr(iph.ip_p), iph.ip_p);
895 switch (IPTOS_TOS(iph.ip_tos)) {
897 strcpy(tos_str, "None");
900 strcpy(tos_str, "Minimize cost");
902 case IPTOS_RELIABILITY:
903 strcpy(tos_str, "Maximize reliability");
905 case IPTOS_THROUGHPUT:
906 strcpy(tos_str, "Maximize throughput");
909 strcpy(tos_str, "Minimize delay");
912 strcpy(tos_str, "Maximize security");
915 strcpy(tos_str, "Unknown. Malformed?");
919 ti = proto_tree_add_item(tree, proto_ip, offset, hlen, NULL);
920 ip_tree = proto_item_add_subtree(ti, ett_ip);
922 proto_tree_add_item(ip_tree, hf_ip_version, offset, 1, hi_nibble(iph.ip_v_hl));
923 proto_tree_add_item_format(ip_tree, hf_ip_hdr_len, offset, 1, hlen,
924 "Header length: %u bytes", hlen);
926 if (g_ip_dscp_actif) {
927 tf = proto_tree_add_item_format(ip_tree, hf_ip_dsfield, offset + 1, 1, iph.ip_tos,
928 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s)", iph.ip_tos,
929 IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
932 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
933 proto_tree_add_item(field_tree, hf_ip_dsfield_dscp, offset + 1, 1, iph.ip_tos);
934 proto_tree_add_item(field_tree, hf_ip_dsfield_cu, offset + 1, 1, iph.ip_tos);
936 tf = proto_tree_add_item_format(ip_tree, hf_ip_tos, offset + 1, 1, iph.ip_tos,
937 "Type of service: 0x%02x (%s)", iph.ip_tos,
938 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
940 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
941 proto_tree_add_item(field_tree, hf_ip_tos_precedence, offset + 1, 1, iph.ip_tos);
942 proto_tree_add_item(field_tree, hf_ip_tos_delay, offset + 1, 1, iph.ip_tos);
943 proto_tree_add_item(field_tree, hf_ip_tos_throughput, offset + 1, 1, iph.ip_tos);
944 proto_tree_add_item(field_tree, hf_ip_tos_reliability, offset + 1, 1, iph.ip_tos);
945 proto_tree_add_item(field_tree, hf_ip_tos_cost, offset + 1, 1, iph.ip_tos);
947 proto_tree_add_item(ip_tree, hf_ip_len, offset + 2, 2, iph.ip_len);
948 proto_tree_add_item(ip_tree, hf_ip_id, offset + 4, 2, iph.ip_id);
950 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
951 tf = proto_tree_add_item(ip_tree, hf_ip_flags, offset + 6, 1, flags);
952 field_tree = proto_item_add_subtree(tf, ett_ip_off);
953 proto_tree_add_item(field_tree, hf_ip_flags_df, offset + 6, 1, flags),
954 proto_tree_add_item(field_tree, hf_ip_flags_mf, offset + 6, 1, flags),
956 proto_tree_add_item(ip_tree, hf_ip_frag_offset, offset + 6, 2,
957 iph.ip_off & IP_OFFSET);
958 proto_tree_add_item(ip_tree, hf_ip_ttl, offset + 8, 1, iph.ip_ttl);
959 proto_tree_add_item_format(ip_tree, hf_ip_proto, offset + 9, 1, iph.ip_p,
960 "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
961 proto_tree_add_item_format(ip_tree, hf_ip_checksum, offset + 10, 2, iph.ip_sum,
962 "Header checksum: 0x%04x (%s)", iph.ip_sum, ip_checksum_state((e_ip*) &pd[offset]));
963 proto_tree_add_item(ip_tree, hf_ip_src, offset + 12, 4, iph.ip_src);
964 proto_tree_add_item(ip_tree, hf_ip_dst, offset + 16, 4, iph.ip_dst);
965 proto_tree_add_item_hidden(ip_tree, hf_ip_addr, offset + 12, 4, iph.ip_src);
966 proto_tree_add_item_hidden(ip_tree, hf_ip_addr, offset + 16, 4, iph.ip_dst);
968 /* Decode IP options, if any. */
969 if (hlen > sizeof (e_ip)) {
970 /* There's more than just the fixed-length header. Decode the
972 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
973 tf = proto_tree_add_text(ip_tree, offset + 20, optlen,
974 "Options: (%d bytes)", optlen);
975 field_tree = proto_item_add_subtree(tf, ett_ip_options);
976 dissect_ip_tcp_options(&pd[offset + 20], offset + 20, optlen,
977 ipopts, N_IP_OPTS, IPOPT_END, field_tree);
981 pi.ipproto = iph.ip_p;
982 pi.iplen = iph.ip_len;
983 pi.iphdrlen = lo_nibble(iph.ip_v_hl);
984 SET_ADDRESS(&pi.net_src, AT_IPv4, 4, &pd[offset + IPH_SRC]);
985 SET_ADDRESS(&pi.src, AT_IPv4, 4, &pd[offset + IPH_SRC]);
986 SET_ADDRESS(&pi.net_dst, AT_IPv4, 4, &pd[offset + IPH_DST]);
987 SET_ADDRESS(&pi.dst, AT_IPv4, 4, &pd[offset + IPH_DST]);
989 /* Skip over header + options */
992 if (iph.ip_off & IP_OFFSET) {
994 if (check_col(fd, COL_PROTOCOL))
995 col_add_str(fd, COL_PROTOCOL, "IP");
996 if (check_col(fd, COL_INFO))
997 col_add_fstr(fd, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%d)",
998 ipprotostr(iph.ip_p), iph.ip_p, iph.ip_off & IP_OFFSET);
999 dissect_data(pd, offset, fd, tree);
1006 dissect_icmp(pd, offset, fd, tree);
1009 dissect_igmp(pd, offset, fd, tree);
1011 case IP_PROTO_EIGRP:
1012 dissect_eigrp(pd, offset, fd, tree);
1015 dissect_tcp(pd, offset, fd, tree);
1018 dissect_udp(pd, offset, fd, tree);
1021 dissect_ospf(pd, offset, fd, tree);
1023 case IP_PROTO_VINES:
1024 dissect_vines_frp(pd, offset, fd, tree);
1027 dissect_rsvp(pd, offset, fd, tree);
1030 advance = dissect_ah(pd, offset, fd, tree);
1035 dissect_gre(pd, offset, fd, tree);
1038 dissect_esp(pd, offset, fd, tree);
1041 dissect_ipv6(pd, offset, fd, tree);
1044 dissect_ip(pd, offset, fd, tree);
1047 dissect_pim(pd, offset, fd, tree);
1049 case IP_PROTO_IPCOMP:
1050 dissect_ipcomp(pd, offset, fd, tree);
1053 dissect_vrrp(pd, offset, fd, tree);
1056 dissect_data(pd, offset, fd, tree);
1062 static const gchar *unreach_str[] = {"Network unreachable",
1064 "Protocol unreachable",
1066 "Fragmentation needed",
1067 "Source route failed",
1068 "Destination network unknown",
1069 "Destination host unknown",
1070 "Source host isolated",
1071 "Network administratively prohibited",
1072 "Host administratively prohibited",
1073 "Network unreachable for TOS",
1074 "Host unreachable for TOS",
1075 "Communication administratively filtered",
1076 "Host precedence violation",
1077 "Precedence cutoff in effect"};
1079 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1081 static const gchar *redir_str[] = {"Redirect for network",
1082 "Redirect for host",
1083 "Redirect for TOS and network",
1084 "Redirect for TOS and host"};
1086 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1088 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
1089 "TTL equals 0 during reassembly"};
1091 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1093 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1095 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1098 dissect_icmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1100 proto_tree *icmp_tree;
1103 gchar type_str[64], code_str[64] = "";
1104 guint8 num_addrs = 0;
1105 guint8 addr_entry_size = 0;
1108 /* Avoids alignment problems on many architectures. */
1109 memcpy(&ih, &pd[offset], sizeof(e_icmp));
1110 /* To do: check for runts, errs, etc. */
1111 cksum = ntohs(ih.icmp_cksum);
1113 switch (ih.icmp_type) {
1114 case ICMP_ECHOREPLY:
1115 strcpy(type_str, "Echo (ping) reply");
1118 strcpy(type_str, "Destination unreachable");
1119 if (ih.icmp_code < N_UNREACH) {
1120 sprintf(code_str, "(%s)", unreach_str[ih.icmp_code]);
1122 strcpy(code_str, "(Unknown - error?)");
1125 case ICMP_SOURCEQUENCH:
1126 strcpy(type_str, "Source quench (flow control)");
1129 strcpy(type_str, "Redirect");
1130 if (ih.icmp_code < N_REDIRECT) {
1131 sprintf(code_str, "(%s)", redir_str[ih.icmp_code]);
1133 strcpy(code_str, "(Unknown - error?)");
1137 strcpy(type_str, "Echo (ping) request");
1139 case ICMP_RTRADVERT:
1140 strcpy(type_str, "Router advertisement");
1142 case ICMP_RTRSOLICIT:
1143 strcpy(type_str, "Router solicitation");
1146 strcpy(type_str, "Time-to-live exceeded");
1147 if (ih.icmp_code < N_TIMXCEED) {
1148 sprintf(code_str, "(%s)", ttl_str[ih.icmp_code]);
1150 strcpy(code_str, "(Unknown - error?)");
1153 case ICMP_PARAMPROB:
1154 strcpy(type_str, "Parameter problem");
1155 if (ih.icmp_code < N_PARAMPROB) {
1156 sprintf(code_str, "(%s)", par_str[ih.icmp_code]);
1158 strcpy(code_str, "(Unknown - error?)");
1162 strcpy(type_str, "Timestamp request");
1164 case ICMP_TSTAMPREPLY:
1165 strcpy(type_str, "Timestamp reply");
1168 strcpy(type_str, "Information request");
1170 case ICMP_IREQREPLY:
1171 strcpy(type_str, "Information reply");
1174 strcpy(type_str, "Address mask request");
1176 case ICMP_MASKREPLY:
1177 strcpy(type_str, "Address mask reply");
1180 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1183 if (check_col(fd, COL_PROTOCOL))
1184 col_add_str(fd, COL_PROTOCOL, "ICMP");
1185 if (check_col(fd, COL_INFO))
1186 col_add_str(fd, COL_INFO, type_str);
1189 ti = proto_tree_add_item(tree, proto_icmp, offset, 4, NULL);
1190 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1191 proto_tree_add_item_format(icmp_tree, hf_icmp_type, offset, 1,
1194 ih.icmp_type, type_str);
1195 proto_tree_add_item_format(icmp_tree, hf_icmp_code, offset + 1, 1,
1198 ih.icmp_code, code_str);
1199 proto_tree_add_item(icmp_tree, hf_icmp_checksum, offset + 2, 2,
1202 /* Decode the second 4 bytes of the packet. */
1203 switch (ih.icmp_type) {
1204 case ICMP_ECHOREPLY:
1207 case ICMP_TSTAMPREPLY:
1209 case ICMP_IREQREPLY:
1211 case ICMP_MASKREPLY:
1212 proto_tree_add_text(icmp_tree, offset + 4, 2, "Identifier: 0x%04x",
1213 pntohs(&pd[offset + 4]));
1214 proto_tree_add_text(icmp_tree, offset + 6, 2, "Sequence number: %u",
1215 pntohs(&pd[offset + 6]));
1219 switch (ih.icmp_code) {
1220 case ICMP_FRAG_NEEDED:
1221 proto_tree_add_text(icmp_tree, offset + 6, 2, "MTU of next hop: %u",
1222 pntohs(&pd[offset + 6]));
1227 case ICMP_RTRADVERT:
1228 num_addrs = pd[offset + 4];
1229 proto_tree_add_text(icmp_tree, offset + 4, 1, "Number of addresses: %u",
1231 addr_entry_size = pd[offset + 5];
1232 proto_tree_add_text(icmp_tree, offset + 5, 1, "Address entry size: %u",
1234 proto_tree_add_text(icmp_tree, offset + 6, 2, "Lifetime: %s",
1235 time_secs_to_str(pntohs(&pd[offset + 6])));
1238 case ICMP_PARAMPROB:
1239 proto_tree_add_text(icmp_tree, offset + 4, 1, "Pointer: %u",
1244 proto_tree_add_text(icmp_tree, offset + 4, 4, "Gateway address: %s",
1245 ip_to_str((guint8 *)&pd[offset + 4]));
1249 /* Decode the additional information in the packet. */
1250 switch (ih.icmp_type) {
1253 case ICMP_PARAMPROB:
1254 case ICMP_SOURCEQUENCH:
1256 /* Decode the IP header and first 64 bits of data from the
1259 XXX - for now, just display it as data; not all dissection
1260 routines can handle a short packet without exploding. */
1261 dissect_data(pd, offset + 8, fd, icmp_tree);
1264 case ICMP_ECHOREPLY:
1266 dissect_data(pd, offset + 8, fd, icmp_tree);
1269 case ICMP_RTRADVERT:
1270 if (addr_entry_size == 2) {
1271 for (i = 0; i < num_addrs; i++) {
1272 proto_tree_add_text(icmp_tree, offset + 8 + (i*8), 4,
1273 "Router address: %s",
1274 ip_to_str((guint8 *)&pd[offset + 8 + (i*8)]));
1275 proto_tree_add_text(icmp_tree, offset + 12 + (i*8), 4,
1276 "Preference level: %d", pntohl(&pd[offset + 12 + (i*8)]));
1279 dissect_data(pd, offset + 8, fd, icmp_tree);
1283 case ICMP_TSTAMPREPLY:
1284 proto_tree_add_text(icmp_tree, offset + 8, 4, "Originate timestamp: %u",
1285 pntohl(&pd[offset + 8]));
1286 proto_tree_add_text(icmp_tree, offset + 12, 4, "Receive timestamp: %u",
1287 pntohl(&pd[offset + 12]));
1288 proto_tree_add_text(icmp_tree, offset + 16, 4, "Transmit timestamp: %u",
1289 pntohl(&pd[offset + 16]));
1293 case ICMP_MASKREPLY:
1294 proto_tree_add_text(icmp_tree, offset + 8, 4, "Address mask: %s (0x%8x)",
1295 ip_to_str((guint8 *)&pd[offset + 8]), pntohl(&pd[offset + 8]));
1302 dissect_igmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1304 proto_tree *igmp_tree;
1307 gchar type_str[64] = "";
1309 /* Avoids alignment problems on many architectures. */
1310 memcpy(&ih, &pd[offset], sizeof(e_igmp));
1311 /* To do: check for runts, errs, etc. */
1312 cksum = ntohs(ih.igmp_cksum);
1314 switch (lo_nibble(ih.igmp_v_t)) {
1316 strcpy(type_str, "Router query");
1319 strcpy(type_str, "Host response (v1)");
1321 case IGMP_V2_LV_GRP:
1322 strcpy(type_str, "Leave group (v2)");
1325 strcpy(type_str, "DVMRP");
1328 strcpy(type_str, "PIM");
1331 strcpy(type_str, "Host response (v2)");
1333 case IGMP_MTRC_RESP:
1334 strcpy(type_str, "Traceroute response");
1337 strcpy(type_str, "Traceroute message");
1340 strcpy(type_str, "Unknown IGMP");
1343 if (check_col(fd, COL_PROTOCOL))
1344 col_add_str(fd, COL_PROTOCOL, "IGMP");
1345 if (check_col(fd, COL_INFO))
1346 col_add_str(fd, COL_INFO, type_str);
1348 ti = proto_tree_add_item(tree, proto_igmp, offset, 8, NULL);
1349 igmp_tree = proto_item_add_subtree(ti, ett_igmp);
1350 proto_tree_add_item(igmp_tree, hf_igmp_version, offset, 1,
1351 hi_nibble(ih.igmp_v_t));
1352 proto_tree_add_item_format(igmp_tree, hf_igmp_type, offset , 1,
1353 lo_nibble(ih.igmp_v_t),
1355 lo_nibble(ih.igmp_v_t), type_str);
1356 proto_tree_add_item_format(igmp_tree, hf_igmp_unused, offset + 1, 1,
1360 proto_tree_add_item(igmp_tree, hf_igmp_checksum, offset + 2, 2,
1362 proto_tree_add_item(igmp_tree, hf_igmp_group, offset + 4, 4,
1368 proto_register_igmp(void)
1370 static hf_register_info hf[] = {
1373 { "Version", "igmp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1377 { "Type", "igmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1381 { "Unused", "igmp.unused", FT_UINT8, BASE_DEC, NULL, 0x0,
1384 { &hf_igmp_checksum,
1385 { "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1389 { "Group address", "igmp.group", FT_IPv4, BASE_NONE, NULL, 0x0,
1392 static gint *ett[] = {
1396 proto_igmp = proto_register_protocol ("Internet Group Management Protocol", "igmp");
1397 proto_register_field_array(proto_igmp, hf, array_length(hf));
1398 proto_register_subtree_array(ett, array_length(ett));
1402 proto_register_ip(void)
1404 static hf_register_info hf[] = {
1407 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1411 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1415 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1418 { &hf_ip_dsfield_dscp,
1419 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1420 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1423 { &hf_ip_dsfield_cu,
1424 { "Currently Unused", "ip.dsfield.cu", FT_UINT8, BASE_DEC, NULL,
1429 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1432 { &hf_ip_tos_precedence,
1433 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1438 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1442 { &hf_ip_tos_throughput,
1443 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1447 { &hf_ip_tos_reliability,
1448 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1453 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1458 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1462 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1466 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1470 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1474 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1478 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1482 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1486 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1489 { &hf_ip_frag_offset,
1490 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1494 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1498 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1502 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1505 static gint *ett[] = {
1512 &ett_ip_option_route,
1513 &ett_ip_option_timestamp,
1516 proto_ip = proto_register_protocol ("Internet Protocol", "ip");
1517 proto_register_field_array(proto_ip, hf, array_length(hf));
1518 proto_register_subtree_array(ett, array_length(ett));
1522 proto_register_icmp(void)
1524 static hf_register_info hf[] = {
1527 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1531 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1534 { &hf_icmp_checksum,
1535 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1538 static gint *ett[] = {
1542 proto_icmp = proto_register_protocol ("Internet Control Message Protocol",
1544 proto_register_field_array(proto_icmp, hf, array_length(hf));
1545 proto_register_subtree_array(ett, array_length(ett));
1548 static int proto_eigrp = -1;
1550 static gint ett_eigrp = -1;
1553 dissect_eigrp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1555 proto_tree *eigrp_tree;
1558 gchar type_str[64] = "";
1560 /* Avoids alignment problems on many architectures. */
1561 static const value_string eigrp_opcode_vals[] = {
1562 { EIGRP_HELLO, "Hello/Ack" },
1563 { EIGRP_UPDATE, "Update" },
1564 { EIGRP_REPLY, "Reply" },
1565 { EIGRP_QUERY, "Query" },
1566 { EIGRP_REQUEST, "Request" },
1570 memcpy(&ih, &pd[offset], sizeof(e_eigrp));
1571 /* To do: check for runts, errs, etc. */
1572 cksum = ntohs(ih.eigrp_checksum);
1574 if (check_col(fd, COL_PROTOCOL))
1575 col_add_str(fd, COL_PROTOCOL, "EIGRP");
1576 if (check_col(fd, COL_INFO))
1577 col_add_str(fd, COL_INFO, type_str);
1580 ti = proto_tree_add_item(tree, proto_eigrp, offset, END_OF_FRAME, NULL);
1581 eigrp_tree = proto_item_add_subtree(ti, ett_eigrp);
1583 proto_tree_add_text(eigrp_tree, offset, 1, "Version: %d", ih.eigrp_version);
1584 proto_tree_add_text(eigrp_tree, offset + 1, 1, "Opcode: %d (%s)", ih.eigrp_opcode,
1585 val_to_str( ih.eigrp_opcode, eigrp_opcode_vals, "Unknown") );
1586 proto_tree_add_text(eigrp_tree, offset + 2, 2, "Checksum: 0x%x", cksum);
1587 proto_tree_add_text(eigrp_tree, offset + 4, 2, "Subnets in local net: %d", ih.eigrp_subnets);
1588 proto_tree_add_text(eigrp_tree, offset + 6, 2, "Networks in Autonomous System: %d", ih.eigrp_networks);
1589 proto_tree_add_text(eigrp_tree, offset + 8, 4, "Sequence Number: 0x%x", ih.eigrp_sequence);
1590 proto_tree_add_text(eigrp_tree, offset + 12, 4, "Autonomous System number: %ld", ih.eigrp_asnumber);
1596 proto_register_eigrp(void)
1598 static gint *ett[] = {
1601 proto_eigrp = proto_register_protocol("Enhanced Interior Gateway Routing Protocol", "eigrp");
1602 proto_register_subtree_array(ett, array_length(ett));