2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.48 1999/09/23 19:05:28 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
45 #ifdef NEED_SNPRINTF_H
51 # include "snprintf.h"
54 #ifndef __PACKET_IP_H__
55 #include "packet-ip.h"
58 static int proto_ip = -1;
59 static int hf_ip_version = -1;
60 static int hf_ip_hdr_len = -1;
61 static int hf_ip_tos = -1;
62 static int hf_ip_tos_precedence = -1;
63 static int hf_ip_len = -1;
64 static int hf_ip_id = -1;
65 static int hf_ip_dst = -1;
66 static int hf_ip_src = -1;
67 static int hf_ip_addr = -1;
68 static int hf_ip_flags = -1;
69 static int hf_ip_frag_offset = -1;
70 static int hf_ip_ttl = -1;
71 static int hf_ip_proto = -1;
72 static int hf_ip_checksum = -1;
74 static int proto_igmp = -1;
75 static int hf_igmp_version = -1;
76 static int hf_igmp_type = -1;
77 static int hf_igmp_unused = -1;
78 static int hf_igmp_checksum = -1;
79 static int hf_igmp_group = -1;
81 static int proto_icmp = -1;
84 /* ICMP structs and definitions */
85 typedef struct _e_icmp {
90 struct { /* Address mask request/reply */
95 struct { /* Timestap request/reply */
102 guint32 zero; /* Unreachable */
106 #define ICMP_ECHOREPLY 0
107 #define ICMP_UNREACH 3
108 #define ICMP_SOURCEQUENCH 4
109 #define ICMP_REDIRECT 5
111 #define ICMP_RTRADVERT 9
112 #define ICMP_RTRSOLICIT 10
113 #define ICMP_TIMXCEED 11
114 #define ICMP_PARAMPROB 12
115 #define ICMP_TSTAMP 13
116 #define ICMP_TSTAMPREPLY 14
118 #define ICMP_IREQREPLY 16
119 #define ICMP_MASKREQ 17
120 #define ICMP_MASKREPLY 18
122 /* ICMP UNREACHABLE */
124 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
125 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
126 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
127 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
128 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
129 #define ICMP_SR_FAILED 5 /* Source Route failed */
130 #define ICMP_NET_UNKNOWN 6
131 #define ICMP_HOST_UNKNOWN 7
132 #define ICMP_HOST_ISOLATED 8
133 #define ICMP_NET_ANO 9
134 #define ICMP_HOST_ANO 10
135 #define ICMP_NET_UNR_TOS 11
136 #define ICMP_HOST_UNR_TOS 12
137 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
138 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
139 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
142 /* IGMP structs and definitions */
143 typedef struct _e_igmp {
144 guint8 igmp_v_t; /* combines igmp_v and igmp_t */
150 #define IGMP_M_QRY 0x01
151 #define IGMP_V1_M_RPT 0x02
152 #define IGMP_V2_LV_GRP 0x07
153 #define IGMP_DVMRP 0x03
154 #define IGMP_PIM 0x04
155 #define IGMP_V2_M_RPT 0x06
156 #define IGMP_MTRC_RESP 0x1e
157 #define IGMP_MTRC 0x1f
159 /* IP structs and definitions */
161 typedef struct _e_ip {
162 guint8 ip_v_hl; /* combines ip_v and ip_hl */
175 #define IP_CE 0x8000 /* Flag: "Congestion" */
176 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
177 #define IP_MF 0x2000 /* Flag: "More Fragments" */
178 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
180 #define IPTOS_TOS_MASK 0x1E
181 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
182 #define IPTOS_NONE 0x00
183 #define IPTOS_LOWCOST 0x02
184 #define IPTOS_RELIABILITY 0x04
185 #define IPTOS_THROUGHPUT 0x08
186 #define IPTOS_LOWDELAY 0x10
187 #define IPTOS_SECURITY 0x1E
189 #define IPTOS_PREC_MASK 0xE0
190 #define IPTOS_PREC(tos) ((tos)&IPTOS_PREC_MASK)
191 #define IPTOS_PREC_NETCONTROL 0xe0
192 #define IPTOS_PREC_INTERNETCONTROL 0xc0
193 #define IPTOS_PREC_CRITIC_ECP 0xa0
194 #define IPTOS_PREC_FLASHOVERRIDE 0x80
195 #define IPTOS_PREC_FLASH 0x60
196 #define IPTOS_PREC_IMMEDIATE 0x40
197 #define IPTOS_PREC_PRIORITY 0x20
198 #define IPTOS_PREC_ROUTINE 0x00
201 #define IPOPT_COPY 0x80
203 #define IPOPT_CONTROL 0x00
204 #define IPOPT_RESERVED1 0x20
205 #define IPOPT_MEASUREMENT 0x40
206 #define IPOPT_RESERVED2 0x60
208 #define IPOPT_END (0 |IPOPT_CONTROL)
209 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
210 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
211 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
212 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
213 #define IPOPT_RR (7 |IPOPT_CONTROL)
214 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
215 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
216 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
218 /* IP option lengths */
219 #define IPOLEN_SEC 11
220 #define IPOLEN_LSRR_MIN 3
221 #define IPOLEN_TIMESTAMP_MIN 5
222 #define IPOLEN_RR_MIN 3
224 #define IPOLEN_SSRR_MIN 3
226 #define IPSEC_UNCLASSIFIED 0x0000
227 #define IPSEC_CONFIDENTIAL 0xF135
228 #define IPSEC_EFTO 0x789A
229 #define IPSEC_MMMM 0xBC4D
230 #define IPSEC_RESTRICTED 0xAF13
231 #define IPSEC_SECRET 0xD788
232 #define IPSEC_TOPSECRET 0x6BC5
233 #define IPSEC_RESERVED1 0x35E2
234 #define IPSEC_RESERVED2 0x9AF1
235 #define IPSEC_RESERVED3 0x4D78
236 #define IPSEC_RESERVED4 0x24BD
237 #define IPSEC_RESERVED5 0x135E
238 #define IPSEC_RESERVED6 0x89AF
239 #define IPSEC_RESERVED7 0xC4D6
240 #define IPSEC_RESERVED8 0xE26B
242 #define IPOPT_TS_TSONLY 0 /* timestamps only */
243 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
244 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
248 capture_ip(const u_char *pd, int offset, guint32 cap_len, packet_counts *ld) {
249 switch (pd[offset + 9]) {
271 dissect_ipopt_security(const ip_tcp_opt *optp, const u_char *opd, int offset,
272 guint optlen, proto_tree *opt_tree)
274 proto_tree *field_tree = NULL;
277 static const value_string secl_vals[] = {
278 {IPSEC_UNCLASSIFIED, "Unclassified"},
279 {IPSEC_CONFIDENTIAL, "Confidential"},
280 {IPSEC_EFTO, "EFTO" },
281 {IPSEC_MMMM, "MMMM" },
282 {IPSEC_RESTRICTED, "Restricted" },
283 {IPSEC_SECRET, "Secret" },
284 {IPSEC_TOPSECRET, "Top secret" },
285 {IPSEC_RESERVED1, "Reserved" },
286 {IPSEC_RESERVED2, "Reserved" },
287 {IPSEC_RESERVED3, "Reserved" },
288 {IPSEC_RESERVED4, "Reserved" },
289 {IPSEC_RESERVED5, "Reserved" },
290 {IPSEC_RESERVED6, "Reserved" },
291 {IPSEC_RESERVED7, "Reserved" },
292 {IPSEC_RESERVED8, "Reserved" },
295 tf = proto_tree_add_text(opt_tree, offset, optlen, "%s:", optp->name);
296 field_tree = proto_item_add_subtree(tf, optp->subtree_index);
300 proto_tree_add_text(field_tree, offset, 2,
301 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
306 proto_tree_add_text(field_tree, offset, 2,
307 "Compartments: %d", val);
311 proto_tree_add_text(field_tree, offset, 2,
312 "Handling restrictions: %c%c", opd[0], opd[1]);
316 proto_tree_add_text(field_tree, offset, 3,
317 "Transmission control code: %c%c%c", opd[0], opd[1], opd[2]);
321 dissect_ipopt_route(const ip_tcp_opt *optp, const u_char *opd, int offset,
322 guint optlen, proto_tree *opt_tree)
324 proto_tree *field_tree = NULL;
330 tf = proto_tree_add_text(opt_tree, offset, optlen, "%s (%d bytes)",
332 field_tree = proto_item_add_subtree(tf, optp->subtree_index);
334 optoffset += 2; /* skip past type and length */
335 optlen -= 2; /* subtract size of type and length */
338 proto_tree_add_text(field_tree, offset + optoffset, 1,
339 "Pointer: %d%s", ptr,
340 ((ptr < 4) ? " (points before first address)" :
341 ((ptr & 3) ? " (points to middle of address)" : "")));
345 ptr--; /* ptr is 1-origin */
349 proto_tree_add_text(field_tree, offset, optlen,
350 "(suboption would go past end of option)");
354 /* Avoids alignment problems on many architectures. */
355 memcpy((char *)&addr, (char *)opd, sizeof(addr));
357 proto_tree_add_text(field_tree, offset + optoffset, 4,
359 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
360 ((optoffset == ptr) ? " <- (current)" : ""));
368 dissect_ipopt_sid(const ip_tcp_opt *optp, const u_char *opd, int offset,
369 guint optlen, proto_tree *opt_tree)
371 proto_tree_add_text(opt_tree, offset, optlen,
372 "%s: %d", optp->name, pntohs(opd));
377 dissect_ipopt_timestamp(const ip_tcp_opt *optp, const u_char *opd,
378 int offset, guint optlen, proto_tree *opt_tree)
380 proto_tree *field_tree = NULL;
385 static const value_string flag_vals[] = {
386 {IPOPT_TS_TSONLY, "Time stamps only" },
387 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
388 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
393 tf = proto_tree_add_text(opt_tree, offset, optlen, "%s:", optp->name);
394 field_tree = proto_item_add_subtree(tf, optp->subtree_index);
396 optoffset += 2; /* skip past type and length */
397 optlen -= 2; /* subtract size of type and length */
400 proto_tree_add_text(field_tree, offset + optoffset, 1,
401 "Pointer: %d%s", ptr,
402 ((ptr < 5) ? " (points before first address)" :
403 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
407 ptr--; /* ptr is 1-origin */
410 proto_tree_add_text(field_tree, offset + optoffset, 1,
411 "Overflow: %d", flg >> 4);
413 proto_tree_add_text(field_tree, offset + optoffset, 1,
414 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
420 if (flg == IPOPT_TS_TSANDADDR) {
422 proto_tree_add_text(field_tree, offset + optoffset, optlen,
423 "(suboption would go past end of option)");
426 /* XXX - check whether it goes past end of packet */
431 proto_tree_add_text(field_tree, offset + optoffset, optlen,
432 "(suboption would go past end of option)");
435 /* XXX - check whether it goes past end of packet */
436 memcpy((char *)&addr, (char *)opd, sizeof(addr));
439 proto_tree_add_text(field_tree, offset, 8,
440 "Address = %s, time stamp = %u",
441 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
446 proto_tree_add_text(field_tree, offset + optoffset, optlen,
447 "(suboption would go past end of option)");
450 /* XXX - check whether it goes past end of packet */
454 proto_tree_add_text(field_tree, offset + optoffset, 4,
455 "Time stamp = %u", ts);
461 static const ip_tcp_opt ipopts[] = {
484 dissect_ipopt_security
488 "Strict source route",
496 "Loose source route",
521 ETT_IP_OPTION_TIMESTAMP,
523 IPOLEN_TIMESTAMP_MIN,
524 dissect_ipopt_timestamp
528 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
530 /* Dissect the IP or TCP options in a packet. */
532 dissect_ip_tcp_options(const u_char *opd, int offset, guint length,
533 const ip_tcp_opt *opttab, int nopts, int eol,
534 proto_tree *opt_tree)
537 const ip_tcp_opt *optp;
538 opt_len_type len_type;
541 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
542 void (*dissect)(const struct ip_tcp_opt *, const u_char *,
543 int, guint, proto_tree *);
548 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
549 if (optp->optcode == opt)
552 if (optp == &opttab[nopts]) {
553 /* We assume that the only NO_LENGTH options are EOL and NOP options,
554 so that we can treat unknown options as VARIABLE_LENGTH with a
555 minimum of 2, and at least be able to move on to the next option
556 by using the length in the option. */
557 optp = NULL; /* indicate that we don't know this option */
558 len_type = VARIABLE_LENGTH;
560 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
564 len_type = optp->len_type;
565 optlen = optp->optlen;
567 dissect = optp->dissect;
569 --length; /* account for type byte */
570 if (len_type != NO_LENGTH) {
571 /* Option has a length. Is it in the packet? */
573 /* Bogus - packet must at least include option code byte and
575 proto_tree_add_text(opt_tree, offset, 1,
576 "%s (length byte past end of options)", name);
579 len = *opd++; /* total including type, len */
580 --length; /* account for length byte */
582 /* Bogus - option length is too short to include option code and
584 proto_tree_add_text(opt_tree, offset, 2,
585 "%s (with too-short option length = %u byte%s)", name,
586 plurality(len, "", "s"));
588 } else if (len - 2 > length) {
589 /* Bogus - option goes past the end of the header. */
590 proto_tree_add_text(opt_tree, offset, length,
591 "%s (option length = %u byte%s says option goes past end of options)",
592 name, len, plurality(len, "", "s"));
594 } else if (len_type == FIXED_LENGTH && len != optlen) {
595 /* Bogus - option length isn't what it's supposed to be for this
597 proto_tree_add_text(opt_tree, offset, len,
598 "%s (with option length = %u byte%s; should be %u)", name,
599 len, plurality(len, "", "s"), optlen);
601 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
602 /* Bogus - option length is less than what it's supposed to be for
604 proto_tree_add_text(opt_tree, offset, len,
605 "%s (with option length = %u byte%s; should be >= %u)", name,
606 len, plurality(len, "", "s"), optlen);
610 proto_tree_add_text(opt_tree, offset, len, "%s (%d byte%s)",
611 name, len, plurality(len, "", "s"));
613 if (dissect != NULL) {
614 /* Option has a dissector. */
615 (*dissect)(optp, opd, offset, len, opt_tree);
617 /* Option has no data, hence no dissector. */
618 proto_tree_add_text(opt_tree, offset, len, "%s", name);
621 len -= 2; /* subtract size of type and length */
627 proto_tree_add_text(opt_tree, offset, 1, "%s", name);
635 static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
636 {IP_PROTO_IGMP, "IGMP"},
637 {IP_PROTO_TCP, "TCP" },
638 {IP_PROTO_UDP, "UDP" },
639 {IP_PROTO_OSPF, "OSPF"},
642 static const value_string precedence_vals[] = {
643 { IPTOS_PREC_ROUTINE, "routine" },
644 { IPTOS_PREC_PRIORITY, "priority" },
645 { IPTOS_PREC_IMMEDIATE, "immediate" },
646 { IPTOS_PREC_FLASH, "flash" },
647 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
648 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
649 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
650 { IPTOS_PREC_NETCONTROL, "network control" },
653 static const value_string iptos_vals[] = {
654 { IPTOS_NONE, "None" },
655 { IPTOS_LOWCOST, "Minimize cost" },
656 { IPTOS_RELIABILITY, "Maximize reliability" },
657 { IPTOS_THROUGHPUT, "Maximize throughput" },
658 { IPTOS_LOWDELAY, "Minimize delay" },
659 { IPTOS_SECURITY, "Maximize security" },
664 dissect_ip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
666 proto_tree *ip_tree, *field_tree;
669 guint hlen, optlen, len;
674 /* To do: check for runts, errs, etc. */
675 /* Avoids alignment problems on many architectures. */
676 memcpy(&iph, &pd[offset], sizeof(e_ip));
677 iph.ip_len = ntohs(iph.ip_len);
678 iph.ip_id = ntohs(iph.ip_id);
679 iph.ip_off = ntohs(iph.ip_off);
680 iph.ip_sum = ntohs(iph.ip_sum);
682 /* Length of IP datagram plus headers above it. */
683 len = iph.ip_len + offset;
685 /* Set the payload and captured-payload lengths to the minima of (the
686 IP length plus the length of the headers above it) and the frame
690 if (pi.captured_len > len)
691 pi.captured_len = len;
693 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
705 /* Names are set in the associated dissect_* routines */
708 if (check_col(fd, COL_PROTOCOL))
709 col_add_str(fd, COL_PROTOCOL, "IP");
710 if (check_col(fd, COL_INFO))
711 col_add_fstr(fd, COL_INFO, "Unknown IP protocol (0x%02x)", iph.ip_p);
714 if (check_col(fd, COL_RES_NET_SRC))
715 col_add_str(fd, COL_RES_NET_SRC, get_hostname(iph.ip_src));
716 if (check_col(fd, COL_UNRES_NET_SRC))
717 col_add_str(fd, COL_UNRES_NET_SRC, ip_to_str((guint8 *) &iph.ip_src));
718 if (check_col(fd, COL_RES_NET_DST))
719 col_add_str(fd, COL_RES_NET_DST, get_hostname(iph.ip_dst));
720 if (check_col(fd, COL_UNRES_NET_DST))
721 col_add_str(fd, COL_UNRES_NET_DST, ip_to_str((guint8 *) &iph.ip_dst));
725 switch (IPTOS_TOS(iph.ip_tos)) {
727 strcpy(tos_str, "None");
730 strcpy(tos_str, "Minimize cost");
732 case IPTOS_RELIABILITY:
733 strcpy(tos_str, "Maximize reliability");
735 case IPTOS_THROUGHPUT:
736 strcpy(tos_str, "Maximize throughput");
739 strcpy(tos_str, "Minimize delay");
742 strcpy(tos_str, "Maximize security");
745 strcpy(tos_str, "Unknown. Malformed?");
749 ti = proto_tree_add_item(tree, proto_ip, offset, hlen, NULL);
750 ip_tree = proto_item_add_subtree(ti, ETT_IP);
752 proto_tree_add_item(ip_tree, hf_ip_version, offset, 1, hi_nibble(iph.ip_v_hl));
753 proto_tree_add_item_format(ip_tree, hf_ip_hdr_len, offset, 1, hlen,
754 "Header length: %d bytes", hlen);
755 tf = proto_tree_add_item_format(ip_tree, hf_ip_tos, offset + 1, 1, iph.ip_tos,
756 "Type of service: 0x%02x (%s)", iph.ip_tos,
757 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
759 field_tree = proto_item_add_subtree(tf, ETT_IP_TOS);
760 proto_tree_add_item_format(field_tree, hf_ip_tos_precedence, offset + 1, 1,
761 iph.ip_tos & IPTOS_PREC_MASK, decode_enumerated_bitfield(iph.ip_tos, IPTOS_PREC_MASK,
762 sizeof (iph.ip_tos)*8, precedence_vals, "%s precedence"));
764 proto_tree_add_text(field_tree, offset + 1, 1, "%s",
765 decode_boolean_bitfield(iph.ip_tos, IPTOS_LOWDELAY,
766 sizeof (iph.ip_tos)*8, "low delay", "normal delay"));
767 proto_tree_add_text(field_tree, offset + 1, 1, "%s",
768 decode_boolean_bitfield(iph.ip_tos, IPTOS_THROUGHPUT,
769 sizeof (iph.ip_tos)*8, "high throughput", "normal throughput"));
770 proto_tree_add_text(field_tree, offset + 1, 1, "%s",
771 decode_boolean_bitfield(iph.ip_tos, IPTOS_RELIABILITY,
772 sizeof (iph.ip_tos)*8, "high reliability", "normal reliability"));
773 proto_tree_add_text(field_tree, offset + 1, 1, "%s",
774 decode_boolean_bitfield(iph.ip_tos, IPTOS_LOWCOST,
775 sizeof (iph.ip_tos)*8, "low cost", "normal cost"));
776 proto_tree_add_item(ip_tree, hf_ip_len, offset + 2, 2, iph.ip_len);
777 proto_tree_add_item_format(ip_tree, hf_ip_id, offset + 4, 2, iph.ip_id, "Identification: 0x%04x",
780 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
781 tf = proto_tree_add_item_format(ip_tree, hf_ip_flags, offset + 6, 1, flags,
782 "Flags: 0x%x", flags);
783 field_tree = proto_item_add_subtree(tf, ETT_IP_OFF);
784 proto_tree_add_text(field_tree, offset + 6, 1, "%s",
785 decode_boolean_bitfield(iph.ip_off >> 12, IP_DF >> 12, 4, "don't fragment",
787 proto_tree_add_text(field_tree, offset + 6, 1, "%s",
788 decode_boolean_bitfield(iph.ip_off >> 12, IP_MF >> 12, 4, "more fragments",
791 proto_tree_add_item(ip_tree, hf_ip_frag_offset, offset + 6, 2,
792 iph.ip_off & IP_OFFSET);
793 proto_tree_add_item(ip_tree, hf_ip_ttl, offset + 8, 1, iph.ip_ttl);
794 proto_tree_add_item(ip_tree, hf_ip_proto, offset + 9, 1, iph.ip_p);
795 proto_tree_add_item_format(ip_tree, hf_ip_checksum, offset + 10, 2, iph.ip_sum,
796 "Header checksum: 0x%04x", iph.ip_sum);
798 proto_tree_add_item(ip_tree, hf_ip_src, offset + 12, 4, iph.ip_src);
799 proto_tree_add_item(ip_tree, hf_ip_dst, offset + 16, 4, iph.ip_dst);
800 proto_tree_add_item_hidden(ip_tree, hf_ip_addr, offset + 12, 4, iph.ip_src);
801 proto_tree_add_item_hidden(ip_tree, hf_ip_addr, offset + 16, 4, iph.ip_dst);
803 /* Decode IP options, if any. */
804 if (hlen > sizeof (e_ip)) {
805 /* There's more than just the fixed-length header. Decode the
807 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
808 tf = proto_tree_add_text(ip_tree, offset + 20, optlen,
809 "Options: (%d bytes)", optlen);
810 field_tree = proto_item_add_subtree(tf, ETT_IP_OPTIONS);
811 dissect_ip_tcp_options(&pd[offset + 20], offset + 20, optlen,
812 ipopts, N_IP_OPTS, IPOPT_END, field_tree);
816 pi.ipproto = iph.ip_p;
817 pi.iplen = iph.ip_len;
818 pi.iphdrlen = lo_nibble(iph.ip_v_hl);
819 pi.ip_src = iph.ip_src;
820 pi.ip_dst = iph.ip_dst;
822 /* Skip over header + options */
825 if (iph.ip_off & IP_OFFSET) {
827 if (check_col(fd, COL_PROTOCOL))
828 col_add_str(fd, COL_PROTOCOL, "IP");
829 if (check_col(fd, COL_INFO))
830 col_add_fstr(fd, COL_INFO, "Fragmented IP protocol (proto=%02x, off=%d)",
831 iph.ip_p, iph.ip_off & IP_OFFSET);
832 dissect_data(pd, offset, fd, tree);
839 dissect_icmp(pd, offset, fd, tree);
842 dissect_igmp(pd, offset, fd, tree);
845 dissect_tcp(pd, offset, fd, tree);
848 dissect_udp(pd, offset, fd, tree);
851 dissect_ospf(pd, offset, fd, tree);
854 dissect_rsvp(pd, offset, fd, tree);
857 advance = dissect_ah(pd, offset, fd, tree);
862 dissect_gre(pd, offset, fd, tree);
865 dissect_esp(pd, offset, fd, tree);
868 dissect_ipv6(pd, offset, fd, tree);
871 dissect_data(pd, offset, fd, tree);
877 static const gchar *unreach_str[] = {"Network unreachable",
879 "Protocol unreachable",
881 "Fragmentation needed",
882 "Source route failed",
883 "Destination network unknown",
884 "Destination host unknown",
885 "Source host isolated",
886 "Network administratively prohibited",
887 "Host administratively prohibited",
888 "Network unreachable for TOS",
889 "Host unreachable for TOS",
890 "Communication administratively filtered",
891 "Host precedence violation",
892 "Precedence cutoff in effect"};
894 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
896 static const gchar *redir_str[] = {"Redirect for network",
898 "Redirect for TOS and network",
899 "Redirect for TOS and host"};
901 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
903 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
904 "TTL equals 0 during reassembly"};
906 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
908 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
910 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
913 dissect_icmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
915 proto_tree *icmp_tree;
918 gchar type_str[64], code_str[64] = "";
919 guint8 num_addrs = 0;
920 guint8 addr_entry_size = 0;
923 /* Avoids alignment problems on many architectures. */
924 memcpy(&ih, &pd[offset], sizeof(e_icmp));
925 /* To do: check for runts, errs, etc. */
926 cksum = ntohs(ih.icmp_cksum);
928 switch (ih.icmp_type) {
930 strcpy(type_str, "Echo (ping) reply");
933 strcpy(type_str, "Destination unreachable");
934 if (ih.icmp_code < N_UNREACH) {
935 sprintf(code_str, "(%s)", unreach_str[ih.icmp_code]);
937 strcpy(code_str, "(Unknown - error?)");
940 case ICMP_SOURCEQUENCH:
941 strcpy(type_str, "Source quench (flow control)");
944 strcpy(type_str, "Redirect");
945 if (ih.icmp_code < N_REDIRECT) {
946 sprintf(code_str, "(%s)", redir_str[ih.icmp_code]);
948 strcpy(code_str, "(Unknown - error?)");
952 strcpy(type_str, "Echo (ping) request");
955 strcpy(type_str, "Router advertisement");
957 case ICMP_RTRSOLICIT:
958 strcpy(type_str, "Router solicitation");
961 strcpy(type_str, "Time-to-live exceeded");
962 if (ih.icmp_code < N_TIMXCEED) {
963 sprintf(code_str, "(%s)", ttl_str[ih.icmp_code]);
965 strcpy(code_str, "(Unknown - error?)");
969 strcpy(type_str, "Parameter problem");
970 if (ih.icmp_code < N_PARAMPROB) {
971 sprintf(code_str, "(%s)", par_str[ih.icmp_code]);
973 strcpy(code_str, "(Unknown - error?)");
977 strcpy(type_str, "Timestamp request");
979 case ICMP_TSTAMPREPLY:
980 strcpy(type_str, "Timestamp reply");
983 strcpy(type_str, "Information request");
986 strcpy(type_str, "Information reply");
989 strcpy(type_str, "Address mask request");
992 strcpy(type_str, "Address mask reply");
995 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
998 if (check_col(fd, COL_PROTOCOL))
999 col_add_str(fd, COL_PROTOCOL, "ICMP");
1000 if (check_col(fd, COL_INFO))
1001 col_add_str(fd, COL_INFO, type_str);
1004 ti = proto_tree_add_item(tree, proto_icmp, offset, 4, NULL);
1005 icmp_tree = proto_item_add_subtree(ti, ETT_ICMP);
1006 proto_tree_add_text(icmp_tree, offset, 1, "Type: %d (%s)",
1007 ih.icmp_type, type_str);
1008 proto_tree_add_text(icmp_tree, offset + 1, 1, "Code: %d %s",
1009 ih.icmp_code, code_str);
1010 proto_tree_add_text(icmp_tree, offset + 2, 2, "Checksum: 0x%04x",
1013 /* Decode the second 4 bytes of the packet. */
1014 switch (ih.icmp_type) {
1015 case ICMP_ECHOREPLY:
1018 case ICMP_TSTAMPREPLY:
1020 case ICMP_IREQREPLY:
1022 case ICMP_MASKREPLY:
1023 proto_tree_add_text(icmp_tree, offset + 4, 2, "Identifier: 0x%04x",
1024 pntohs(&pd[offset + 4]));
1025 proto_tree_add_text(icmp_tree, offset + 6, 2, "Sequence number: %u",
1026 pntohs(&pd[offset + 6]));
1030 switch (ih.icmp_code) {
1031 case ICMP_FRAG_NEEDED:
1032 proto_tree_add_text(icmp_tree, offset + 6, 2, "MTU of next hop: %u",
1033 pntohs(&pd[offset + 6]));
1038 case ICMP_RTRADVERT:
1039 num_addrs = pd[offset + 4];
1040 proto_tree_add_text(icmp_tree, offset + 4, 1, "Number of addresses: %u",
1042 addr_entry_size = pd[offset + 5];
1043 proto_tree_add_text(icmp_tree, offset + 5, 1, "Address entry size: %u",
1045 proto_tree_add_text(icmp_tree, offset + 6, 2, "Lifetime: %s",
1046 time_secs_to_str(pntohs(&pd[offset + 6])));
1049 case ICMP_PARAMPROB:
1050 proto_tree_add_text(icmp_tree, offset + 4, 1, "Pointer: %u",
1055 proto_tree_add_text(icmp_tree, offset + 4, 4, "Gateway address: %s",
1056 ip_to_str((guint8 *)&pd[offset + 4]));
1060 /* Decode the additional information in the packet. */
1061 switch (ih.icmp_type) {
1064 case ICMP_PARAMPROB:
1065 case ICMP_SOURCEQUENCH:
1067 /* Decode the IP header and first 64 bits of data from the
1070 XXX - for now, just display it as data; not all dissection
1071 routines can handle a short packet without exploding. */
1072 dissect_data(pd, offset + 8, fd, icmp_tree);
1075 case ICMP_ECHOREPLY:
1077 dissect_data(pd, offset + 8, fd, icmp_tree);
1080 case ICMP_RTRADVERT:
1081 if (addr_entry_size == 2) {
1082 for (i = 0; i < num_addrs; i++) {
1083 proto_tree_add_text(icmp_tree, offset + 8 + (i*8), 4,
1084 "Router address: %s",
1085 ip_to_str((guint8 *)&pd[offset + 8 + (i*8)]));
1086 proto_tree_add_text(icmp_tree, offset + 12 + (i*8), 4,
1087 "Preference level: %d", pntohl(&pd[offset + 12 + (i*8)]));
1090 dissect_data(pd, offset + 8, fd, icmp_tree);
1094 case ICMP_TSTAMPREPLY:
1095 proto_tree_add_text(icmp_tree, offset + 8, 4, "Originate timestamp: %u",
1096 pntohl(&pd[offset + 8]));
1097 proto_tree_add_text(icmp_tree, offset + 12, 4, "Receive timestamp: %u",
1098 pntohl(&pd[offset + 12]));
1099 proto_tree_add_text(icmp_tree, offset + 16, 4, "Transmit timestamp: %u",
1100 pntohl(&pd[offset + 16]));
1104 case ICMP_MASKREPLY:
1105 proto_tree_add_text(icmp_tree, offset + 8, 4, "Address mask: %s (0x%8x)",
1106 ip_to_str((guint8 *)&pd[offset + 8]), pntohl(&pd[offset + 8]));
1113 dissect_igmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
1115 proto_tree *igmp_tree;
1118 gchar type_str[64] = "";
1120 /* Avoids alignment problems on many architectures. */
1121 memcpy(&ih, &pd[offset], sizeof(e_igmp));
1122 /* To do: check for runts, errs, etc. */
1123 cksum = ntohs(ih.igmp_cksum);
1125 switch (lo_nibble(ih.igmp_v_t)) {
1127 strcpy(type_str, "Router query");
1130 strcpy(type_str, "Host response (v1)");
1132 case IGMP_V2_LV_GRP:
1133 strcpy(type_str, "Leave group (v2)");
1136 strcpy(type_str, "DVMRP");
1139 strcpy(type_str, "PIM");
1142 strcpy(type_str, "Host reponse (v2)");
1144 case IGMP_MTRC_RESP:
1145 strcpy(type_str, "Traceroute response");
1148 strcpy(type_str, "Traceroute message");
1151 strcpy(type_str, "Unknown IGMP");
1154 if (check_col(fd, COL_PROTOCOL))
1155 col_add_str(fd, COL_PROTOCOL, "IGMP");
1156 if (check_col(fd, COL_INFO))
1157 col_add_str(fd, COL_INFO, type_str);
1159 ti = proto_tree_add_item(tree, proto_igmp, offset, 8, NULL);
1160 igmp_tree = proto_item_add_subtree(ti, ETT_IGMP);
1161 proto_tree_add_text(igmp_tree, offset, 1, "Version: %d",
1162 hi_nibble(ih.igmp_v_t));
1163 proto_tree_add_text(igmp_tree, offset , 1, "Type: %d (%s)",
1164 lo_nibble(ih.igmp_v_t), type_str);
1165 proto_tree_add_text(igmp_tree, offset + 1, 1, "Unused: 0x%02x",
1167 proto_tree_add_text(igmp_tree, offset + 2, 2, "Checksum: 0x%04x",
1169 proto_tree_add_text(igmp_tree, offset + 4, 4, "Group address: %s",
1170 ip_to_str((guint8 *) &ih.igmp_gaddr));
1175 proto_register_igmp(void)
1177 static hf_register_info hf[] = {
1180 { "Version", "igmp.version", FT_UINT8, NULL }},
1183 { "Type", "igmp.type", FT_UINT8, NULL }},
1186 { "Unused", "igmp.unused", FT_UINT8, NULL }},
1188 { &hf_igmp_checksum,
1189 { "Checksum", "igmp.checksum", FT_UINT16, NULL }},
1192 { "Group address", "igmp.group", FT_IPv4, NULL }}
1195 proto_igmp = proto_register_protocol ("Internet Group Management Protocol", "igmp");
1196 proto_register_field_array(proto_igmp, hf, array_length(hf));
1200 proto_register_ip(void)
1202 static hf_register_info hf[] = {
1205 { "Version", "ip.version", FT_UINT8, NULL }},
1208 { "Header Length", "ip.hdr_len", FT_UINT8, NULL }},
1211 { "Type of Service", "ip.tos", FT_UINT8, NULL }},
1213 { &hf_ip_tos_precedence,
1214 { "Precedence", "ip.tos.precedence", FT_VALS_UINT8, VALS(precedence_vals) }},
1217 { "Total Length", "ip.len", FT_UINT16 }},
1220 { "Identification", "ip.id", FT_UINT32 }},
1223 { "Destination", "ip.dst", FT_IPv4, NULL }},
1226 { "Source", "ip.src", FT_IPv4, NULL }},
1229 { "Source or Destination Address", "ip.addr", FT_IPv4, NULL }},
1232 { "Flags", "ip.flags", FT_UINT8, NULL }},
1234 { &hf_ip_frag_offset,
1235 { "Fragment offset", "ip.frag_offset", FT_UINT16, NULL }},
1238 { "Time to live", "ip.ttl", FT_UINT8, NULL }},
1241 { "Protocol", "ip.proto", FT_VALS_UINT8, VALS(proto_vals) }},
1244 { "Header checksum", "ip.checksum", FT_UINT16, NULL }}
1247 proto_ip = proto_register_protocol ("Internet Protocol", "ip");
1248 proto_register_field_array(proto_ip, hf, array_length(hf));
1252 proto_register_icmp(void)
1254 proto_icmp = proto_register_protocol ("Internet Control Message Protocol", "icmp");