2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.74 2000/02/15 21:02:15 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 #include "packet-gre.h"
54 #include "packet-ip.h"
55 #include "packet-ipsec.h"
56 #include "packet-ipv6.h"
57 #include "packet-ospf.h"
58 #include "packet-pim.h"
59 #include "packet-rsvp.h"
60 #include "packet-tcp.h"
61 #include "packet-udp.h"
62 #include "packet-vines.h"
63 #include "packet-vrrp.h"
65 static void dissect_eigrp(const u_char *, int, frame_data *, proto_tree *);
66 static void dissect_icmp(const u_char *, int, frame_data *, proto_tree *);
67 static void dissect_igmp(const u_char *, int, frame_data *, proto_tree *);
70 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
71 gboolean g_ip_dscp_actif = TRUE;
73 static int proto_ip = -1;
74 static int hf_ip_version = -1;
75 static int hf_ip_hdr_len = -1;
76 static int hf_ip_dsfield = -1;
77 static int hf_ip_dsfield_dscp = -1;
78 static int hf_ip_dsfield_cu = -1;
79 static int hf_ip_tos = -1;
80 static int hf_ip_tos_precedence = -1;
81 static int hf_ip_tos_delay = -1;
82 static int hf_ip_tos_throughput = -1;
83 static int hf_ip_tos_reliability = -1;
84 static int hf_ip_tos_cost = -1;
85 static int hf_ip_len = -1;
86 static int hf_ip_id = -1;
87 static int hf_ip_dst = -1;
88 static int hf_ip_src = -1;
89 static int hf_ip_addr = -1;
90 static int hf_ip_flags = -1;
91 static int hf_ip_flags_df = -1;
92 static int hf_ip_flags_mf = -1;
93 static int hf_ip_frag_offset = -1;
94 static int hf_ip_ttl = -1;
95 static int hf_ip_proto = -1;
96 static int hf_ip_checksum = -1;
98 static gint ett_ip = -1;
99 static gint ett_ip_dsfield = -1;
100 static gint ett_ip_tos = -1;
101 static gint ett_ip_off = -1;
102 static gint ett_ip_options = -1;
103 static gint ett_ip_option_sec = -1;
104 static gint ett_ip_option_route = -1;
105 static gint ett_ip_option_timestamp = -1;
107 static int proto_igmp = -1;
108 static int hf_igmp_version = -1;
109 static int hf_igmp_type = -1;
110 static int hf_igmp_unused = -1;
111 static int hf_igmp_checksum = -1;
112 static int hf_igmp_group = -1;
114 static gint ett_igmp = -1;
116 static int proto_icmp = -1;
117 static int hf_icmp_type = -1;
118 static int hf_icmp_code = -1;
119 static int hf_icmp_checksum = -1;
121 static gint ett_icmp = -1;
123 /* ICMP structs and definitions */
124 typedef struct _e_icmp {
129 struct { /* Address mask request/reply */
134 struct { /* Timestap request/reply */
141 guint32 zero; /* Unreachable */
145 #define ICMP_ECHOREPLY 0
146 #define ICMP_UNREACH 3
147 #define ICMP_SOURCEQUENCH 4
148 #define ICMP_REDIRECT 5
150 #define ICMP_RTRADVERT 9
151 #define ICMP_RTRSOLICIT 10
152 #define ICMP_TIMXCEED 11
153 #define ICMP_PARAMPROB 12
154 #define ICMP_TSTAMP 13
155 #define ICMP_TSTAMPREPLY 14
157 #define ICMP_IREQREPLY 16
158 #define ICMP_MASKREQ 17
159 #define ICMP_MASKREPLY 18
161 /* ICMP UNREACHABLE */
163 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
164 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
165 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
166 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
167 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
168 #define ICMP_SR_FAILED 5 /* Source Route failed */
169 #define ICMP_NET_UNKNOWN 6
170 #define ICMP_HOST_UNKNOWN 7
171 #define ICMP_HOST_ISOLATED 8
172 #define ICMP_NET_ANO 9
173 #define ICMP_HOST_ANO 10
174 #define ICMP_NET_UNR_TOS 11
175 #define ICMP_HOST_UNR_TOS 12
176 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
177 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
178 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
181 /* IGMP structs and definitions */
182 typedef struct _e_igmp {
183 guint8 igmp_v_t; /* combines igmp_v and igmp_t */
189 #define IGMP_M_QRY 0x01
190 #define IGMP_V1_M_RPT 0x02
191 #define IGMP_V2_LV_GRP 0x07
192 #define IGMP_DVMRP 0x03
193 #define IGMP_PIM 0x04
194 #define IGMP_V2_M_RPT 0x06
195 #define IGMP_MTRC_RESP 0x1e
196 #define IGMP_MTRC 0x1f
198 /* EIGRP Structs and Definitions. */
202 #define EIGRP_UPDATE 0x01
203 #define EIGRP_REQUEST 0x02
204 #define EIGRP_QUERY 0x03
205 #define EIGRP_REPLY 0x04
206 #define EIGRP_HELLO 0x05
208 typedef struct _e_eigrp
210 guint8 eigrp_version;
212 guint16 eigrp_checksum;
213 guint16 eigrp_subnets;
214 guint16 eigrp_networks;
215 guint32 eigrp_sequence;
216 guint32 eigrp_asnumber;
218 guint8 eigrp_subtype1;
219 guint16 eigrp_length1;
220 guint16 eigrp_holdtime;
222 guint8 eigrp_subtype2;
223 guint16 eigrp_length2;
228 /* IP structs and definitions */
232 guint8 ip_v_hl; /* combines ip_v and ip_hl */
244 /* Offsets of fields within an IP header. */
256 /* Minimum IP header length. */
257 #define IPH_MIN_LEN 20
260 #define IP_CE 0x8000 /* Flag: "Congestion" */
261 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
262 #define IP_MF 0x2000 /* Flag: "More Fragments" */
263 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
265 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
266 #define IPDSFIELD_DSCP_MASK 0xFC
267 #define IPDSFIELD_DSCP_SHIFT 2
268 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
269 #define IPDSFIELD_DSCP_DEFAULT 0x00
270 #define IPDSFIELD_DSCP_CS1 0x08
271 #define IPDSFIELD_DSCP_CS2 0x10
272 #define IPDSFIELD_DSCP_CS3 0x18
273 #define IPDSFIELD_DSCP_CS4 0x20
274 #define IPDSFIELD_DSCP_CS5 0x28
275 #define IPDSFIELD_DSCP_CS6 0x30
276 #define IPDSFIELD_DSCP_CS7 0x38
277 #define IPDSFIELD_DSCP_AF11 0x0A
278 #define IPDSFIELD_DSCP_AF12 0x0C
279 #define IPDSFIELD_DSCP_AF13 0x0E
280 #define IPDSFIELD_DSCP_AF21 0x12
281 #define IPDSFIELD_DSCP_AF22 0x14
282 #define IPDSFIELD_DSCP_AF23 0x16
283 #define IPDSFIELD_DSCP_AF31 0x1A
284 #define IPDSFIELD_DSCP_AF32 0x1C
285 #define IPDSFIELD_DSCP_AF33 0x1E
286 #define IPDSFIELD_DSCP_AF41 0x22
287 #define IPDSFIELD_DSCP_AF42 0x24
288 #define IPDSFIELD_DSCP_AF43 0x26
289 #define IPDSFIELD_DSCP_EF 0x2E
290 #define IPDSFIELD_CU_MASK 0x03
292 /* IP TOS, superseded by the DS Field, RFC 2474. */
293 #define IPTOS_TOS_MASK 0x1E
294 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
295 #define IPTOS_NONE 0x00
296 #define IPTOS_LOWCOST 0x02
297 #define IPTOS_RELIABILITY 0x04
298 #define IPTOS_THROUGHPUT 0x08
299 #define IPTOS_LOWDELAY 0x10
300 #define IPTOS_SECURITY 0x1E
302 #define IPTOS_PREC_MASK 0xE0
303 #define IPTOS_PREC_SHIFT 5
304 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
305 #define IPTOS_PREC_NETCONTROL 7
306 #define IPTOS_PREC_INTERNETCONTROL 6
307 #define IPTOS_PREC_CRITIC_ECP 5
308 #define IPTOS_PREC_FLASHOVERRIDE 4
309 #define IPTOS_PREC_FLASH 3
310 #define IPTOS_PREC_IMMEDIATE 2
311 #define IPTOS_PREC_PRIORITY 1
312 #define IPTOS_PREC_ROUTINE 0
315 #define IPOPT_COPY 0x80
317 #define IPOPT_CONTROL 0x00
318 #define IPOPT_RESERVED1 0x20
319 #define IPOPT_MEASUREMENT 0x40
320 #define IPOPT_RESERVED2 0x60
322 #define IPOPT_END (0 |IPOPT_CONTROL)
323 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
324 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
325 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
326 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
327 #define IPOPT_RR (7 |IPOPT_CONTROL)
328 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
329 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
330 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
332 /* IP option lengths */
333 #define IPOLEN_SEC 11
334 #define IPOLEN_LSRR_MIN 3
335 #define IPOLEN_TIMESTAMP_MIN 5
336 #define IPOLEN_RR_MIN 3
338 #define IPOLEN_SSRR_MIN 3
340 #define IPSEC_UNCLASSIFIED 0x0000
341 #define IPSEC_CONFIDENTIAL 0xF135
342 #define IPSEC_EFTO 0x789A
343 #define IPSEC_MMMM 0xBC4D
344 #define IPSEC_RESTRICTED 0xAF13
345 #define IPSEC_SECRET 0xD788
346 #define IPSEC_TOPSECRET 0x6BC5
347 #define IPSEC_RESERVED1 0x35E2
348 #define IPSEC_RESERVED2 0x9AF1
349 #define IPSEC_RESERVED3 0x4D78
350 #define IPSEC_RESERVED4 0x24BD
351 #define IPSEC_RESERVED5 0x135E
352 #define IPSEC_RESERVED6 0x89AF
353 #define IPSEC_RESERVED7 0xC4D6
354 #define IPSEC_RESERVED8 0xE26B
356 #define IPOPT_TS_TSONLY 0 /* timestamps only */
357 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
358 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
362 capture_ip(const u_char *pd, int offset, packet_counts *ld) {
363 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
367 switch (pd[offset + 9]) {
392 dissect_ipopt_security(const ip_tcp_opt *optp, const u_char *opd, int offset,
393 guint optlen, proto_tree *opt_tree)
395 proto_tree *field_tree = NULL;
398 static const value_string secl_vals[] = {
399 {IPSEC_UNCLASSIFIED, "Unclassified"},
400 {IPSEC_CONFIDENTIAL, "Confidential"},
401 {IPSEC_EFTO, "EFTO" },
402 {IPSEC_MMMM, "MMMM" },
403 {IPSEC_RESTRICTED, "Restricted" },
404 {IPSEC_SECRET, "Secret" },
405 {IPSEC_TOPSECRET, "Top secret" },
406 {IPSEC_RESERVED1, "Reserved" },
407 {IPSEC_RESERVED2, "Reserved" },
408 {IPSEC_RESERVED3, "Reserved" },
409 {IPSEC_RESERVED4, "Reserved" },
410 {IPSEC_RESERVED5, "Reserved" },
411 {IPSEC_RESERVED6, "Reserved" },
412 {IPSEC_RESERVED7, "Reserved" },
413 {IPSEC_RESERVED8, "Reserved" },
416 tf = proto_tree_add_text(opt_tree, offset, optlen, "%s:", optp->name);
417 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
421 proto_tree_add_text(field_tree, offset, 2,
422 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
427 proto_tree_add_text(field_tree, offset, 2,
428 "Compartments: %d", val);
432 proto_tree_add_text(field_tree, offset, 2,
433 "Handling restrictions: %c%c", opd[0], opd[1]);
437 proto_tree_add_text(field_tree, offset, 3,
438 "Transmission control code: %c%c%c", opd[0], opd[1], opd[2]);
442 dissect_ipopt_route(const ip_tcp_opt *optp, const u_char *opd, int offset,
443 guint optlen, proto_tree *opt_tree)
445 proto_tree *field_tree = NULL;
451 tf = proto_tree_add_text(opt_tree, offset, optlen, "%s (%d bytes)",
453 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
455 optoffset += 2; /* skip past type and length */
456 optlen -= 2; /* subtract size of type and length */
459 proto_tree_add_text(field_tree, offset + optoffset, 1,
460 "Pointer: %d%s", ptr,
461 ((ptr < 4) ? " (points before first address)" :
462 ((ptr & 3) ? " (points to middle of address)" : "")));
466 ptr--; /* ptr is 1-origin */
470 proto_tree_add_text(field_tree, offset, optlen,
471 "(suboption would go past end of option)");
475 /* Avoids alignment problems on many architectures. */
476 memcpy((char *)&addr, (char *)opd, sizeof(addr));
478 proto_tree_add_text(field_tree, offset + optoffset, 4,
480 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
481 ((optoffset == ptr) ? " <- (current)" : ""));
489 dissect_ipopt_sid(const ip_tcp_opt *optp, const u_char *opd, int offset,
490 guint optlen, proto_tree *opt_tree)
492 proto_tree_add_text(opt_tree, offset, optlen,
493 "%s: %d", optp->name, pntohs(opd));
498 dissect_ipopt_timestamp(const ip_tcp_opt *optp, const u_char *opd,
499 int offset, guint optlen, proto_tree *opt_tree)
501 proto_tree *field_tree = NULL;
506 static const value_string flag_vals[] = {
507 {IPOPT_TS_TSONLY, "Time stamps only" },
508 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
509 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
514 tf = proto_tree_add_text(opt_tree, offset, optlen, "%s:", optp->name);
515 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
517 optoffset += 2; /* skip past type and length */
518 optlen -= 2; /* subtract size of type and length */
521 proto_tree_add_text(field_tree, offset + optoffset, 1,
522 "Pointer: %d%s", ptr,
523 ((ptr < 5) ? " (points before first address)" :
524 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
528 ptr--; /* ptr is 1-origin */
531 proto_tree_add_text(field_tree, offset + optoffset, 1,
532 "Overflow: %d", flg >> 4);
534 proto_tree_add_text(field_tree, offset + optoffset, 1,
535 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
541 if (flg == IPOPT_TS_TSANDADDR) {
542 /* XXX - check whether it goes past end of packet */
544 proto_tree_add_text(field_tree, offset + optoffset, optlen,
545 "(suboption would go past end of option)");
548 memcpy((char *)&addr, (char *)opd, sizeof(addr));
553 proto_tree_add_text(field_tree, offset + optoffset, 8,
554 "Address = %s, time stamp = %u",
555 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
560 proto_tree_add_text(field_tree, offset + optoffset, optlen,
561 "(suboption would go past end of option)");
564 /* XXX - check whether it goes past end of packet */
568 proto_tree_add_text(field_tree, offset + optoffset, 4,
569 "Time stamp = %u", ts);
575 static const ip_tcp_opt ipopts[] = {
598 dissect_ipopt_security
602 "Strict source route",
603 &ett_ip_option_route,
610 "Loose source route",
611 &ett_ip_option_route,
619 &ett_ip_option_route,
635 &ett_ip_option_timestamp,
637 IPOLEN_TIMESTAMP_MIN,
638 dissect_ipopt_timestamp
642 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
644 /* Dissect the IP or TCP options in a packet. */
646 dissect_ip_tcp_options(const u_char *opd, int offset, guint length,
647 const ip_tcp_opt *opttab, int nopts, int eol,
648 proto_tree *opt_tree)
651 const ip_tcp_opt *optp;
652 opt_len_type len_type;
655 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
656 void (*dissect)(const struct ip_tcp_opt *, const u_char *,
657 int, guint, proto_tree *);
662 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
663 if (optp->optcode == opt)
666 if (optp == &opttab[nopts]) {
667 /* We assume that the only NO_LENGTH options are EOL and NOP options,
668 so that we can treat unknown options as VARIABLE_LENGTH with a
669 minimum of 2, and at least be able to move on to the next option
670 by using the length in the option. */
671 optp = NULL; /* indicate that we don't know this option */
672 len_type = VARIABLE_LENGTH;
674 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
678 len_type = optp->len_type;
679 optlen = optp->optlen;
681 dissect = optp->dissect;
683 --length; /* account for type byte */
684 if (len_type != NO_LENGTH) {
685 /* Option has a length. Is it in the packet? */
687 /* Bogus - packet must at least include option code byte and
689 proto_tree_add_text(opt_tree, offset, 1,
690 "%s (length byte past end of options)", name);
693 len = *opd++; /* total including type, len */
694 --length; /* account for length byte */
696 /* Bogus - option length is too short to include option code and
698 proto_tree_add_text(opt_tree, offset, 2,
699 "%s (with too-short option length = %u byte%s)", name,
700 len, plurality(len, "", "s"));
702 } else if (len - 2 > length) {
703 /* Bogus - option goes past the end of the header. */
704 proto_tree_add_text(opt_tree, offset, length,
705 "%s (option length = %u byte%s says option goes past end of options)",
706 name, len, plurality(len, "", "s"));
708 } else if (len_type == FIXED_LENGTH && len != optlen) {
709 /* Bogus - option length isn't what it's supposed to be for this
711 proto_tree_add_text(opt_tree, offset, len,
712 "%s (with option length = %u byte%s; should be %u)", name,
713 len, plurality(len, "", "s"), optlen);
715 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
716 /* Bogus - option length is less than what it's supposed to be for
718 proto_tree_add_text(opt_tree, offset, len,
719 "%s (with option length = %u byte%s; should be >= %u)", name,
720 len, plurality(len, "", "s"), optlen);
724 proto_tree_add_text(opt_tree, offset, len, "%s (%d byte%s)",
725 name, len, plurality(len, "", "s"));
727 if (dissect != NULL) {
728 /* Option has a dissector. */
729 (*dissect)(optp, opd, offset, len, opt_tree);
731 /* Option has no data, hence no dissector. */
732 proto_tree_add_text(opt_tree, offset, len, "%s", name);
735 len -= 2; /* subtract size of type and length */
741 proto_tree_add_text(opt_tree, offset, 1, "%s", name);
749 static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
750 {IP_PROTO_IGMP, "IGMP"},
751 {IP_PROTO_EIGRP, "IGRP/EIGRP"},
752 {IP_PROTO_TCP, "TCP" },
753 {IP_PROTO_UDP, "UDP" },
754 {IP_PROTO_OSPF, "OSPF"},
755 {IP_PROTO_RSVP, "RSVP"},
756 {IP_PROTO_AH, "AH" },
757 {IP_PROTO_GRE, "GRE" },
758 {IP_PROTO_ESP, "ESP" },
759 {IP_PROTO_IPV6, "IPv6"},
760 {IP_PROTO_PIM, "PIM" },
761 {IP_PROTO_VINES,"VINES"},
764 static const value_string dscp_vals[] = {
765 { IPDSFIELD_DSCP_DEFAULT, "Default" },
766 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
767 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
768 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
769 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
770 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
771 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
772 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
773 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
774 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
775 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
776 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
777 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
778 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
779 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
780 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
781 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
782 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
783 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
784 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
785 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
788 static const value_string precedence_vals[] = {
789 { IPTOS_PREC_ROUTINE, "routine" },
790 { IPTOS_PREC_PRIORITY, "priority" },
791 { IPTOS_PREC_IMMEDIATE, "immediate" },
792 { IPTOS_PREC_FLASH, "flash" },
793 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
794 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
795 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
796 { IPTOS_PREC_NETCONTROL, "network control" },
799 static const value_string iptos_vals[] = {
800 { IPTOS_NONE, "None" },
801 { IPTOS_LOWCOST, "Minimize cost" },
802 { IPTOS_RELIABILITY, "Maximize reliability" },
803 { IPTOS_THROUGHPUT, "Maximize throughput" },
804 { IPTOS_LOWDELAY, "Minimize delay" },
805 { IPTOS_SECURITY, "Maximize security" },
809 static const true_false_string tos_set_low = {
814 static const true_false_string tos_set_high = {
819 static const true_false_string flags_set_truth = {
824 static char *ip_checksum_state(e_ip *iph)
827 unsigned char *Ptr, *PtrEnd;
831 PtrEnd = (lo_nibble(iph->ip_v_hl) * 4 + (char *)iph);
832 for (Ptr = (unsigned char *) iph; Ptr < PtrEnd; Ptr += 2) {
833 memcpy(&word, Ptr, sizeof word);
837 Sum = (Sum & 0xFFFF) + (Sum >> 16);
838 Sum = (Sum & 0xFFFF) + (Sum >> 16);
847 dissect_ip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
849 proto_tree *ip_tree, *field_tree;
852 guint hlen, optlen, len;
857 /* To do: check for errs, etc. */
858 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
859 dissect_data(pd, offset, fd, tree);
863 /* Avoids alignment problems on many architectures. */
864 memcpy(&iph, &pd[offset], sizeof(e_ip));
865 iph.ip_len = ntohs(iph.ip_len);
866 iph.ip_id = ntohs(iph.ip_id);
867 iph.ip_off = ntohs(iph.ip_off);
868 iph.ip_sum = ntohs(iph.ip_sum);
870 /* Length of IP datagram plus headers above it. */
871 len = iph.ip_len + offset;
873 /* Set the payload and captured-payload lengths to the minima of (the
874 IP length plus the length of the headers above it) and the frame
878 if (pi.captured_len > len)
879 pi.captured_len = len;
881 /* XXX - check to make sure this is at least IPH_MIN_LEN. */
882 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
896 /* Names are set in the associated dissect_* routines */
899 if (check_col(fd, COL_PROTOCOL))
900 col_add_str(fd, COL_PROTOCOL, "IP");
901 if (check_col(fd, COL_INFO))
902 col_add_fstr(fd, COL_INFO, "%s (0x%02x)",
903 ipprotostr(iph.ip_p), iph.ip_p);
908 switch (IPTOS_TOS(iph.ip_tos)) {
910 strcpy(tos_str, "None");
913 strcpy(tos_str, "Minimize cost");
915 case IPTOS_RELIABILITY:
916 strcpy(tos_str, "Maximize reliability");
918 case IPTOS_THROUGHPUT:
919 strcpy(tos_str, "Maximize throughput");
922 strcpy(tos_str, "Minimize delay");
925 strcpy(tos_str, "Maximize security");
928 strcpy(tos_str, "Unknown. Malformed?");
932 ti = proto_tree_add_item(tree, proto_ip, offset, hlen, NULL);
933 ip_tree = proto_item_add_subtree(ti, ett_ip);
935 proto_tree_add_item(ip_tree, hf_ip_version, offset, 1, hi_nibble(iph.ip_v_hl));
936 proto_tree_add_item_format(ip_tree, hf_ip_hdr_len, offset, 1, hlen,
937 "Header length: %u bytes", hlen);
939 if (g_ip_dscp_actif) {
940 tf = proto_tree_add_item_format(ip_tree, hf_ip_dsfield, offset + 1, 1, iph.ip_tos,
941 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s)", iph.ip_tos,
942 IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
945 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
946 proto_tree_add_item(field_tree, hf_ip_dsfield_dscp, offset + 1, 1, iph.ip_tos);
947 proto_tree_add_item(field_tree, hf_ip_dsfield_cu, offset + 1, 1, iph.ip_tos);
949 tf = proto_tree_add_item_format(ip_tree, hf_ip_tos, offset + 1, 1, iph.ip_tos,
950 "Type of service: 0x%02x (%s)", iph.ip_tos,
951 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
953 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
954 proto_tree_add_item(field_tree, hf_ip_tos_precedence, offset + 1, 1, iph.ip_tos);
955 proto_tree_add_item(field_tree, hf_ip_tos_delay, offset + 1, 1, iph.ip_tos);
956 proto_tree_add_item(field_tree, hf_ip_tos_throughput, offset + 1, 1, iph.ip_tos);
957 proto_tree_add_item(field_tree, hf_ip_tos_reliability, offset + 1, 1, iph.ip_tos);
958 proto_tree_add_item(field_tree, hf_ip_tos_cost, offset + 1, 1, iph.ip_tos);
960 proto_tree_add_item(ip_tree, hf_ip_len, offset + 2, 2, iph.ip_len);
961 proto_tree_add_item(ip_tree, hf_ip_id, offset + 4, 2, iph.ip_id);
963 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
964 tf = proto_tree_add_item(ip_tree, hf_ip_flags, offset + 6, 1, flags);
965 field_tree = proto_item_add_subtree(tf, ett_ip_off);
966 proto_tree_add_item(field_tree, hf_ip_flags_df, offset + 6, 1, flags),
967 proto_tree_add_item(field_tree, hf_ip_flags_mf, offset + 6, 1, flags),
969 proto_tree_add_item(ip_tree, hf_ip_frag_offset, offset + 6, 2,
970 iph.ip_off & IP_OFFSET);
971 proto_tree_add_item(ip_tree, hf_ip_ttl, offset + 8, 1, iph.ip_ttl);
972 proto_tree_add_item_format(ip_tree, hf_ip_proto, offset + 9, 1, iph.ip_p,
973 "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
974 proto_tree_add_item_format(ip_tree, hf_ip_checksum, offset + 10, 2, iph.ip_sum,
975 "Header checksum: 0x%04x (%s)", iph.ip_sum, ip_checksum_state((e_ip*) &pd[offset]));
976 proto_tree_add_item(ip_tree, hf_ip_src, offset + 12, 4, iph.ip_src);
977 proto_tree_add_item(ip_tree, hf_ip_dst, offset + 16, 4, iph.ip_dst);
978 proto_tree_add_item_hidden(ip_tree, hf_ip_addr, offset + 12, 4, iph.ip_src);
979 proto_tree_add_item_hidden(ip_tree, hf_ip_addr, offset + 16, 4, iph.ip_dst);
981 /* Decode IP options, if any. */
982 if (hlen > sizeof (e_ip)) {
983 /* There's more than just the fixed-length header. Decode the
985 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
986 tf = proto_tree_add_text(ip_tree, offset + 20, optlen,
987 "Options: (%d bytes)", optlen);
988 field_tree = proto_item_add_subtree(tf, ett_ip_options);
989 dissect_ip_tcp_options(&pd[offset + 20], offset + 20, optlen,
990 ipopts, N_IP_OPTS, IPOPT_END, field_tree);
994 pi.ipproto = iph.ip_p;
995 pi.iplen = iph.ip_len;
996 pi.iphdrlen = lo_nibble(iph.ip_v_hl);
997 SET_ADDRESS(&pi.net_src, AT_IPv4, 4, &pd[offset + IPH_SRC]);
998 SET_ADDRESS(&pi.src, AT_IPv4, 4, &pd[offset + IPH_SRC]);
999 SET_ADDRESS(&pi.net_dst, AT_IPv4, 4, &pd[offset + IPH_DST]);
1000 SET_ADDRESS(&pi.dst, AT_IPv4, 4, &pd[offset + IPH_DST]);
1002 /* Skip over header + options */
1005 if (iph.ip_off & IP_OFFSET) {
1007 if (check_col(fd, COL_PROTOCOL))
1008 col_add_str(fd, COL_PROTOCOL, "IP");
1009 if (check_col(fd, COL_INFO))
1010 col_add_fstr(fd, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%d)",
1011 ipprotostr(iph.ip_p), iph.ip_p, iph.ip_off & IP_OFFSET);
1012 dissect_data(pd, offset, fd, tree);
1019 dissect_icmp(pd, offset, fd, tree);
1022 dissect_igmp(pd, offset, fd, tree);
1024 case IP_PROTO_EIGRP:
1025 dissect_eigrp(pd, offset, fd, tree);
1028 dissect_tcp(pd, offset, fd, tree);
1031 dissect_udp(pd, offset, fd, tree);
1034 dissect_ospf(pd, offset, fd, tree);
1036 case IP_PROTO_VINES:
1037 dissect_vines_frp(pd, offset, fd, tree);
1040 dissect_rsvp(pd, offset, fd, tree);
1043 advance = dissect_ah(pd, offset, fd, tree);
1048 dissect_gre(pd, offset, fd, tree);
1051 dissect_esp(pd, offset, fd, tree);
1054 dissect_ipv6(pd, offset, fd, tree);
1057 dissect_ip(pd, offset, fd, tree);
1060 dissect_pim(pd, offset, fd, tree);
1062 case IP_PROTO_IPCOMP:
1063 dissect_ipcomp(pd, offset, fd, tree);
1066 dissect_vrrp(pd, offset, fd, tree);
1069 dissect_data(pd, offset, fd, tree);
1075 static const gchar *unreach_str[] = {"Network unreachable",
1077 "Protocol unreachable",
1079 "Fragmentation needed",
1080 "Source route failed",
1081 "Destination network unknown",
1082 "Destination host unknown",
1083 "Source host isolated",
1084 "Network administratively prohibited",
1085 "Host administratively prohibited",
1086 "Network unreachable for TOS",
1087 "Host unreachable for TOS",
1088 "Communication administratively filtered",
1089 "Host precedence violation",
1090 "Precedence cutoff in effect"};
1092 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
1094 static const gchar *redir_str[] = {"Redirect for network",
1095 "Redirect for host",
1096 "Redirect for TOS and network",
1097 "Redirect for TOS and host"};
1099 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
1101 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
1102 "TTL equals 0 during reassembly"};
1104 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
1106 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1108 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
1111 dissect_icmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1113 proto_tree *icmp_tree;
1116 gchar type_str[64], code_str[64] = "";
1117 guint8 num_addrs = 0;
1118 guint8 addr_entry_size = 0;
1121 /* Avoids alignment problems on many architectures. */
1122 memcpy(&ih, &pd[offset], sizeof(e_icmp));
1123 /* To do: check for runts, errs, etc. */
1124 cksum = ntohs(ih.icmp_cksum);
1126 switch (ih.icmp_type) {
1127 case ICMP_ECHOREPLY:
1128 strcpy(type_str, "Echo (ping) reply");
1131 strcpy(type_str, "Destination unreachable");
1132 if (ih.icmp_code < N_UNREACH) {
1133 sprintf(code_str, "(%s)", unreach_str[ih.icmp_code]);
1135 strcpy(code_str, "(Unknown - error?)");
1138 case ICMP_SOURCEQUENCH:
1139 strcpy(type_str, "Source quench (flow control)");
1142 strcpy(type_str, "Redirect");
1143 if (ih.icmp_code < N_REDIRECT) {
1144 sprintf(code_str, "(%s)", redir_str[ih.icmp_code]);
1146 strcpy(code_str, "(Unknown - error?)");
1150 strcpy(type_str, "Echo (ping) request");
1152 case ICMP_RTRADVERT:
1153 strcpy(type_str, "Router advertisement");
1155 case ICMP_RTRSOLICIT:
1156 strcpy(type_str, "Router solicitation");
1159 strcpy(type_str, "Time-to-live exceeded");
1160 if (ih.icmp_code < N_TIMXCEED) {
1161 sprintf(code_str, "(%s)", ttl_str[ih.icmp_code]);
1163 strcpy(code_str, "(Unknown - error?)");
1166 case ICMP_PARAMPROB:
1167 strcpy(type_str, "Parameter problem");
1168 if (ih.icmp_code < N_PARAMPROB) {
1169 sprintf(code_str, "(%s)", par_str[ih.icmp_code]);
1171 strcpy(code_str, "(Unknown - error?)");
1175 strcpy(type_str, "Timestamp request");
1177 case ICMP_TSTAMPREPLY:
1178 strcpy(type_str, "Timestamp reply");
1181 strcpy(type_str, "Information request");
1183 case ICMP_IREQREPLY:
1184 strcpy(type_str, "Information reply");
1187 strcpy(type_str, "Address mask request");
1189 case ICMP_MASKREPLY:
1190 strcpy(type_str, "Address mask reply");
1193 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1196 if (check_col(fd, COL_PROTOCOL))
1197 col_add_str(fd, COL_PROTOCOL, "ICMP");
1198 if (check_col(fd, COL_INFO))
1199 col_add_str(fd, COL_INFO, type_str);
1202 ti = proto_tree_add_item(tree, proto_icmp, offset, 4, NULL);
1203 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1204 proto_tree_add_item_format(icmp_tree, hf_icmp_type, offset, 1,
1207 ih.icmp_type, type_str);
1208 proto_tree_add_item_format(icmp_tree, hf_icmp_code, offset + 1, 1,
1211 ih.icmp_code, code_str);
1212 proto_tree_add_item(icmp_tree, hf_icmp_checksum, offset + 2, 2,
1215 /* Decode the second 4 bytes of the packet. */
1216 switch (ih.icmp_type) {
1217 case ICMP_ECHOREPLY:
1220 case ICMP_TSTAMPREPLY:
1222 case ICMP_IREQREPLY:
1224 case ICMP_MASKREPLY:
1225 proto_tree_add_text(icmp_tree, offset + 4, 2, "Identifier: 0x%04x",
1226 pntohs(&pd[offset + 4]));
1227 proto_tree_add_text(icmp_tree, offset + 6, 2, "Sequence number: %u",
1228 pntohs(&pd[offset + 6]));
1232 switch (ih.icmp_code) {
1233 case ICMP_FRAG_NEEDED:
1234 proto_tree_add_text(icmp_tree, offset + 6, 2, "MTU of next hop: %u",
1235 pntohs(&pd[offset + 6]));
1240 case ICMP_RTRADVERT:
1241 num_addrs = pd[offset + 4];
1242 proto_tree_add_text(icmp_tree, offset + 4, 1, "Number of addresses: %u",
1244 addr_entry_size = pd[offset + 5];
1245 proto_tree_add_text(icmp_tree, offset + 5, 1, "Address entry size: %u",
1247 proto_tree_add_text(icmp_tree, offset + 6, 2, "Lifetime: %s",
1248 time_secs_to_str(pntohs(&pd[offset + 6])));
1251 case ICMP_PARAMPROB:
1252 proto_tree_add_text(icmp_tree, offset + 4, 1, "Pointer: %u",
1257 proto_tree_add_text(icmp_tree, offset + 4, 4, "Gateway address: %s",
1258 ip_to_str((guint8 *)&pd[offset + 4]));
1262 /* Decode the additional information in the packet. */
1263 switch (ih.icmp_type) {
1266 case ICMP_PARAMPROB:
1267 case ICMP_SOURCEQUENCH:
1269 /* Decode the IP header and first 64 bits of data from the
1272 XXX - for now, just display it as data; not all dissection
1273 routines can handle a short packet without exploding. */
1274 dissect_data(pd, offset + 8, fd, icmp_tree);
1277 case ICMP_ECHOREPLY:
1279 dissect_data(pd, offset + 8, fd, icmp_tree);
1282 case ICMP_RTRADVERT:
1283 if (addr_entry_size == 2) {
1284 for (i = 0; i < num_addrs; i++) {
1285 proto_tree_add_text(icmp_tree, offset + 8 + (i*8), 4,
1286 "Router address: %s",
1287 ip_to_str((guint8 *)&pd[offset + 8 + (i*8)]));
1288 proto_tree_add_text(icmp_tree, offset + 12 + (i*8), 4,
1289 "Preference level: %d", pntohl(&pd[offset + 12 + (i*8)]));
1292 dissect_data(pd, offset + 8, fd, icmp_tree);
1296 case ICMP_TSTAMPREPLY:
1297 proto_tree_add_text(icmp_tree, offset + 8, 4, "Originate timestamp: %u",
1298 pntohl(&pd[offset + 8]));
1299 proto_tree_add_text(icmp_tree, offset + 12, 4, "Receive timestamp: %u",
1300 pntohl(&pd[offset + 12]));
1301 proto_tree_add_text(icmp_tree, offset + 16, 4, "Transmit timestamp: %u",
1302 pntohl(&pd[offset + 16]));
1306 case ICMP_MASKREPLY:
1307 proto_tree_add_text(icmp_tree, offset + 8, 4, "Address mask: %s (0x%8x)",
1308 ip_to_str((guint8 *)&pd[offset + 8]), pntohl(&pd[offset + 8]));
1315 dissect_igmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1317 proto_tree *igmp_tree;
1320 gchar type_str[64] = "";
1322 /* Avoids alignment problems on many architectures. */
1323 memcpy(&ih, &pd[offset], sizeof(e_igmp));
1324 /* To do: check for runts, errs, etc. */
1325 cksum = ntohs(ih.igmp_cksum);
1327 switch (lo_nibble(ih.igmp_v_t)) {
1329 strcpy(type_str, "Router query");
1332 strcpy(type_str, "Host response (v1)");
1334 case IGMP_V2_LV_GRP:
1335 strcpy(type_str, "Leave group (v2)");
1338 strcpy(type_str, "DVMRP");
1341 strcpy(type_str, "PIM");
1344 strcpy(type_str, "Host response (v2)");
1346 case IGMP_MTRC_RESP:
1347 strcpy(type_str, "Traceroute response");
1350 strcpy(type_str, "Traceroute message");
1353 strcpy(type_str, "Unknown IGMP");
1356 if (check_col(fd, COL_PROTOCOL))
1357 col_add_str(fd, COL_PROTOCOL, "IGMP");
1358 if (check_col(fd, COL_INFO))
1359 col_add_str(fd, COL_INFO, type_str);
1361 ti = proto_tree_add_item(tree, proto_igmp, offset, 8, NULL);
1362 igmp_tree = proto_item_add_subtree(ti, ett_igmp);
1363 proto_tree_add_item(igmp_tree, hf_igmp_version, offset, 1,
1364 hi_nibble(ih.igmp_v_t));
1365 proto_tree_add_item_format(igmp_tree, hf_igmp_type, offset , 1,
1366 lo_nibble(ih.igmp_v_t),
1368 lo_nibble(ih.igmp_v_t), type_str);
1369 proto_tree_add_item_format(igmp_tree, hf_igmp_unused, offset + 1, 1,
1373 proto_tree_add_item(igmp_tree, hf_igmp_checksum, offset + 2, 2,
1375 proto_tree_add_item(igmp_tree, hf_igmp_group, offset + 4, 4,
1381 proto_register_igmp(void)
1383 static hf_register_info hf[] = {
1386 { "Version", "igmp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1390 { "Type", "igmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1394 { "Unused", "igmp.unused", FT_UINT8, BASE_DEC, NULL, 0x0,
1397 { &hf_igmp_checksum,
1398 { "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1402 { "Group address", "igmp.group", FT_IPv4, BASE_NONE, NULL, 0x0,
1405 static gint *ett[] = {
1409 proto_igmp = proto_register_protocol ("Internet Group Management Protocol", "igmp");
1410 proto_register_field_array(proto_igmp, hf, array_length(hf));
1411 proto_register_subtree_array(ett, array_length(ett));
1415 proto_register_ip(void)
1417 static hf_register_info hf[] = {
1420 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1424 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1428 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1431 { &hf_ip_dsfield_dscp,
1432 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1433 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1436 { &hf_ip_dsfield_cu,
1437 { "Currently Unused", "ip.dsfield.cu", FT_UINT8, BASE_DEC, NULL,
1442 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1445 { &hf_ip_tos_precedence,
1446 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1451 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1455 { &hf_ip_tos_throughput,
1456 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1460 { &hf_ip_tos_reliability,
1461 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1466 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1471 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1475 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1479 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1483 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1487 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1491 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1495 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1499 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1502 { &hf_ip_frag_offset,
1503 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1507 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1511 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1515 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1518 static gint *ett[] = {
1525 &ett_ip_option_route,
1526 &ett_ip_option_timestamp,
1529 proto_ip = proto_register_protocol ("Internet Protocol", "ip");
1530 proto_register_field_array(proto_ip, hf, array_length(hf));
1531 proto_register_subtree_array(ett, array_length(ett));
1535 proto_register_icmp(void)
1537 static hf_register_info hf[] = {
1540 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1544 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1547 { &hf_icmp_checksum,
1548 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1551 static gint *ett[] = {
1555 proto_icmp = proto_register_protocol ("Internet Control Message Protocol",
1557 proto_register_field_array(proto_icmp, hf, array_length(hf));
1558 proto_register_subtree_array(ett, array_length(ett));
1561 static int proto_eigrp = -1;
1563 static gint ett_eigrp = -1;
1566 dissect_eigrp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1568 proto_tree *eigrp_tree;
1571 gchar type_str[64] = "";
1573 /* Avoids alignment problems on many architectures. */
1574 static const value_string eigrp_opcode_vals[] = {
1575 { EIGRP_HELLO, "Hello/Ack" },
1576 { EIGRP_UPDATE, "Update" },
1577 { EIGRP_REPLY, "Reply" },
1578 { EIGRP_QUERY, "Query" },
1579 { EIGRP_REQUEST, "Request" },
1583 memcpy(&ih, &pd[offset], sizeof(e_eigrp));
1584 /* To do: check for runts, errs, etc. */
1585 cksum = ntohs(ih.eigrp_checksum);
1587 if (check_col(fd, COL_PROTOCOL))
1588 col_add_str(fd, COL_PROTOCOL, "EIGRP");
1589 if (check_col(fd, COL_INFO))
1590 col_add_str(fd, COL_INFO, type_str);
1593 ti = proto_tree_add_item(tree, proto_eigrp, offset, END_OF_FRAME, NULL);
1594 eigrp_tree = proto_item_add_subtree(ti, ett_eigrp);
1596 proto_tree_add_text(eigrp_tree, offset, 1, "Version: %d", ih.eigrp_version);
1597 proto_tree_add_text(eigrp_tree, offset + 1, 1, "Opcode: %d (%s)", ih.eigrp_opcode,
1598 val_to_str( ih.eigrp_opcode, eigrp_opcode_vals, "Unknown") );
1599 proto_tree_add_text(eigrp_tree, offset + 2, 2, "Checksum: 0x%x", cksum);
1600 proto_tree_add_text(eigrp_tree, offset + 4, 2, "Subnets in local net: %d", ih.eigrp_subnets);
1601 proto_tree_add_text(eigrp_tree, offset + 6, 2, "Networks in Autonomous System: %d", ih.eigrp_networks);
1602 proto_tree_add_text(eigrp_tree, offset + 8, 4, "Sequence Number: 0x%x", ih.eigrp_sequence);
1603 proto_tree_add_text(eigrp_tree, offset + 12, 4, "Autonomous System number: %ld", ih.eigrp_asnumber);
1609 proto_register_eigrp(void)
1611 static gint *ett[] = {
1614 proto_eigrp = proto_register_protocol("Enhanced Interior Gateway Routing Protocol", "eigrp");
1615 proto_register_subtree_array(ett, array_length(ett));