2 * Routines for IP and miscellaneous IP protocol packet disassembly
4 * $Id: packet-ip.c,v 1.94 2000/06/20 13:21:55 gram Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
44 #ifdef NEED_SNPRINTF_H
50 # include "snprintf.h"
56 #include "packet-ip.h"
57 #include "packet-ipsec.h"
59 static void dissect_icmp(const u_char *, int, frame_data *, proto_tree *);
60 static void dissect_igmp(const u_char *, int, frame_data *, proto_tree *);
63 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
64 gboolean g_ip_dscp_actif = TRUE;
66 static int proto_ip = -1;
67 static int hf_ip_version = -1;
68 static int hf_ip_hdr_len = -1;
69 static int hf_ip_dsfield = -1;
70 static int hf_ip_dsfield_dscp = -1;
71 static int hf_ip_dsfield_cu = -1;
72 static int hf_ip_tos = -1;
73 static int hf_ip_tos_precedence = -1;
74 static int hf_ip_tos_delay = -1;
75 static int hf_ip_tos_throughput = -1;
76 static int hf_ip_tos_reliability = -1;
77 static int hf_ip_tos_cost = -1;
78 static int hf_ip_len = -1;
79 static int hf_ip_id = -1;
80 static int hf_ip_dst = -1;
81 static int hf_ip_src = -1;
82 static int hf_ip_addr = -1;
83 static int hf_ip_flags = -1;
84 static int hf_ip_flags_df = -1;
85 static int hf_ip_flags_mf = -1;
86 static int hf_ip_frag_offset = -1;
87 static int hf_ip_ttl = -1;
88 static int hf_ip_proto = -1;
89 static int hf_ip_checksum = -1;
91 static gint ett_ip = -1;
92 static gint ett_ip_dsfield = -1;
93 static gint ett_ip_tos = -1;
94 static gint ett_ip_off = -1;
95 static gint ett_ip_options = -1;
96 static gint ett_ip_option_sec = -1;
97 static gint ett_ip_option_route = -1;
98 static gint ett_ip_option_timestamp = -1;
100 /* Used by IPv6 as well, so not static */
101 dissector_table_t ip_dissector_table;
103 static int proto_igmp = -1;
104 static int hf_igmp_version = -1;
105 static int hf_igmp_type = -1;
106 static int hf_igmp_unused = -1;
107 static int hf_igmp_checksum = -1;
108 static int hf_igmp_group = -1;
110 static gint ett_igmp = -1;
112 static int proto_icmp = -1;
113 static int hf_icmp_type = -1;
114 static int hf_icmp_code = -1;
115 static int hf_icmp_checksum = -1;
117 static gint ett_icmp = -1;
119 /* ICMP structs and definitions */
120 typedef struct _e_icmp {
125 struct { /* Address mask request/reply */
130 struct { /* Timestap request/reply */
137 guint32 zero; /* Unreachable */
141 #define ICMP_ECHOREPLY 0
142 #define ICMP_UNREACH 3
143 #define ICMP_SOURCEQUENCH 4
144 #define ICMP_REDIRECT 5
146 #define ICMP_RTRADVERT 9
147 #define ICMP_RTRSOLICIT 10
148 #define ICMP_TIMXCEED 11
149 #define ICMP_PARAMPROB 12
150 #define ICMP_TSTAMP 13
151 #define ICMP_TSTAMPREPLY 14
153 #define ICMP_IREQREPLY 16
154 #define ICMP_MASKREQ 17
155 #define ICMP_MASKREPLY 18
157 /* ICMP UNREACHABLE */
159 #define ICMP_NET_UNREACH 0 /* Network Unreachable */
160 #define ICMP_HOST_UNREACH 1 /* Host Unreachable */
161 #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
162 #define ICMP_PORT_UNREACH 3 /* Port Unreachable */
163 #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
164 #define ICMP_SR_FAILED 5 /* Source Route failed */
165 #define ICMP_NET_UNKNOWN 6
166 #define ICMP_HOST_UNKNOWN 7
167 #define ICMP_HOST_ISOLATED 8
168 #define ICMP_NET_ANO 9
169 #define ICMP_HOST_ANO 10
170 #define ICMP_NET_UNR_TOS 11
171 #define ICMP_HOST_UNR_TOS 12
172 #define ICMP_PKT_FILTERED 13 /* Packet filtered */
173 #define ICMP_PREC_VIOLATION 14 /* Precedence violation */
174 #define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
177 /* IGMP structs and definitions */
178 typedef struct _e_igmp {
179 guint8 igmp_v_t; /* combines igmp_v and igmp_t */
185 #define IGMP_M_QRY 0x01
186 #define IGMP_V1_M_RPT 0x02
187 #define IGMP_V2_LV_GRP 0x07
188 #define IGMP_DVMRP 0x03
189 #define IGMP_PIM 0x04
190 #define IGMP_V2_M_RPT 0x06
191 #define IGMP_MTRC_RESP 0x1e
192 #define IGMP_MTRC 0x1f
194 /* IP structs and definitions */
198 guint8 ip_v_hl; /* combines ip_v and ip_hl */
210 /* Offsets of fields within an IP header. */
222 /* Minimum IP header length. */
223 #define IPH_MIN_LEN 20
226 #define IP_CE 0x8000 /* Flag: "Congestion" */
227 #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
228 #define IP_MF 0x2000 /* Flag: "More Fragments" */
229 #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
231 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
232 #define IPDSFIELD_DSCP_MASK 0xFC
233 #define IPDSFIELD_DSCP_SHIFT 2
234 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
235 #define IPDSFIELD_DSCP_DEFAULT 0x00
236 #define IPDSFIELD_DSCP_CS1 0x08
237 #define IPDSFIELD_DSCP_CS2 0x10
238 #define IPDSFIELD_DSCP_CS3 0x18
239 #define IPDSFIELD_DSCP_CS4 0x20
240 #define IPDSFIELD_DSCP_CS5 0x28
241 #define IPDSFIELD_DSCP_CS6 0x30
242 #define IPDSFIELD_DSCP_CS7 0x38
243 #define IPDSFIELD_DSCP_AF11 0x0A
244 #define IPDSFIELD_DSCP_AF12 0x0C
245 #define IPDSFIELD_DSCP_AF13 0x0E
246 #define IPDSFIELD_DSCP_AF21 0x12
247 #define IPDSFIELD_DSCP_AF22 0x14
248 #define IPDSFIELD_DSCP_AF23 0x16
249 #define IPDSFIELD_DSCP_AF31 0x1A
250 #define IPDSFIELD_DSCP_AF32 0x1C
251 #define IPDSFIELD_DSCP_AF33 0x1E
252 #define IPDSFIELD_DSCP_AF41 0x22
253 #define IPDSFIELD_DSCP_AF42 0x24
254 #define IPDSFIELD_DSCP_AF43 0x26
255 #define IPDSFIELD_DSCP_EF 0x2E
256 #define IPDSFIELD_CU_MASK 0x03
258 /* IP TOS, superseded by the DS Field, RFC 2474. */
259 #define IPTOS_TOS_MASK 0x1E
260 #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
261 #define IPTOS_NONE 0x00
262 #define IPTOS_LOWCOST 0x02
263 #define IPTOS_RELIABILITY 0x04
264 #define IPTOS_THROUGHPUT 0x08
265 #define IPTOS_LOWDELAY 0x10
266 #define IPTOS_SECURITY 0x1E
268 #define IPTOS_PREC_MASK 0xE0
269 #define IPTOS_PREC_SHIFT 5
270 #define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
271 #define IPTOS_PREC_NETCONTROL 7
272 #define IPTOS_PREC_INTERNETCONTROL 6
273 #define IPTOS_PREC_CRITIC_ECP 5
274 #define IPTOS_PREC_FLASHOVERRIDE 4
275 #define IPTOS_PREC_FLASH 3
276 #define IPTOS_PREC_IMMEDIATE 2
277 #define IPTOS_PREC_PRIORITY 1
278 #define IPTOS_PREC_ROUTINE 0
281 #define IPOPT_COPY 0x80
283 #define IPOPT_CONTROL 0x00
284 #define IPOPT_RESERVED1 0x20
285 #define IPOPT_MEASUREMENT 0x40
286 #define IPOPT_RESERVED2 0x60
288 #define IPOPT_END (0 |IPOPT_CONTROL)
289 #define IPOPT_NOOP (1 |IPOPT_CONTROL)
290 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
291 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
292 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
293 #define IPOPT_RR (7 |IPOPT_CONTROL)
294 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
295 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
296 #define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
298 /* IP option lengths */
299 #define IPOLEN_SEC 11
300 #define IPOLEN_LSRR_MIN 3
301 #define IPOLEN_TIMESTAMP_MIN 5
302 #define IPOLEN_RR_MIN 3
304 #define IPOLEN_SSRR_MIN 3
306 #define IPSEC_UNCLASSIFIED 0x0000
307 #define IPSEC_CONFIDENTIAL 0xF135
308 #define IPSEC_EFTO 0x789A
309 #define IPSEC_MMMM 0xBC4D
310 #define IPSEC_RESTRICTED 0xAF13
311 #define IPSEC_SECRET 0xD788
312 #define IPSEC_TOPSECRET 0x6BC5
313 #define IPSEC_RESERVED1 0x35E2
314 #define IPSEC_RESERVED2 0x9AF1
315 #define IPSEC_RESERVED3 0x4D78
316 #define IPSEC_RESERVED4 0x24BD
317 #define IPSEC_RESERVED5 0x135E
318 #define IPSEC_RESERVED6 0x89AF
319 #define IPSEC_RESERVED7 0xC4D6
320 #define IPSEC_RESERVED8 0xE26B
322 #define IPOPT_TS_TSONLY 0 /* timestamps only */
323 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
324 #define IPOPT_TS_PRESPEC 3 /* specified modules only */
328 capture_ip(const u_char *pd, int offset, packet_counts *ld) {
329 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
333 switch (pd[offset + 9]) {
361 dissect_ipopt_security(const ip_tcp_opt *optp, const u_char *opd, int offset,
362 guint optlen, proto_tree *opt_tree)
364 proto_tree *field_tree = NULL;
367 static const value_string secl_vals[] = {
368 {IPSEC_UNCLASSIFIED, "Unclassified"},
369 {IPSEC_CONFIDENTIAL, "Confidential"},
370 {IPSEC_EFTO, "EFTO" },
371 {IPSEC_MMMM, "MMMM" },
372 {IPSEC_RESTRICTED, "Restricted" },
373 {IPSEC_SECRET, "Secret" },
374 {IPSEC_TOPSECRET, "Top secret" },
375 {IPSEC_RESERVED1, "Reserved" },
376 {IPSEC_RESERVED2, "Reserved" },
377 {IPSEC_RESERVED3, "Reserved" },
378 {IPSEC_RESERVED4, "Reserved" },
379 {IPSEC_RESERVED5, "Reserved" },
380 {IPSEC_RESERVED6, "Reserved" },
381 {IPSEC_RESERVED7, "Reserved" },
382 {IPSEC_RESERVED8, "Reserved" },
385 tf = proto_tree_add_text(opt_tree, NullTVB, offset, optlen, "%s:", optp->name);
386 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
390 proto_tree_add_text(field_tree, NullTVB, offset, 2,
391 "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
396 proto_tree_add_text(field_tree, NullTVB, offset, 2,
397 "Compartments: %u", val);
401 proto_tree_add_text(field_tree, NullTVB, offset, 2,
402 "Handling restrictions: %c%c", opd[0], opd[1]);
406 proto_tree_add_text(field_tree, NullTVB, offset, 3,
407 "Transmission control code: %c%c%c", opd[0], opd[1], opd[2]);
411 dissect_ipopt_route(const ip_tcp_opt *optp, const u_char *opd, int offset,
412 guint optlen, proto_tree *opt_tree)
414 proto_tree *field_tree = NULL;
420 tf = proto_tree_add_text(opt_tree, NullTVB, offset, optlen, "%s (%u bytes)",
422 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
424 optoffset += 2; /* skip past type and length */
425 optlen -= 2; /* subtract size of type and length */
428 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
429 "Pointer: %d%s", ptr,
430 ((ptr < 4) ? " (points before first address)" :
431 ((ptr & 3) ? " (points to middle of address)" : "")));
435 ptr--; /* ptr is 1-origin */
439 proto_tree_add_text(field_tree, NullTVB, offset, optlen,
440 "(suboption would go past end of option)");
444 /* Avoids alignment problems on many architectures. */
445 memcpy((char *)&addr, (char *)opd, sizeof(addr));
447 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 4,
449 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
450 ((optoffset == ptr) ? " <- (current)" : ""));
458 dissect_ipopt_sid(const ip_tcp_opt *optp, const u_char *opd, int offset,
459 guint optlen, proto_tree *opt_tree)
461 proto_tree_add_text(opt_tree, NullTVB, offset, optlen,
462 "%s: %d", optp->name, pntohs(opd));
467 dissect_ipopt_timestamp(const ip_tcp_opt *optp, const u_char *opd,
468 int offset, guint optlen, proto_tree *opt_tree)
470 proto_tree *field_tree = NULL;
475 static const value_string flag_vals[] = {
476 {IPOPT_TS_TSONLY, "Time stamps only" },
477 {IPOPT_TS_TSANDADDR, "Time stamp and address" },
478 {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
483 tf = proto_tree_add_text(opt_tree, NullTVB, offset, optlen, "%s:", optp->name);
484 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
486 optoffset += 2; /* skip past type and length */
487 optlen -= 2; /* subtract size of type and length */
490 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
491 "Pointer: %d%s", ptr,
492 ((ptr < 5) ? " (points before first address)" :
493 (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
497 ptr--; /* ptr is 1-origin */
500 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
501 "Overflow: %d", flg >> 4);
503 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 1,
504 "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
510 if (flg == IPOPT_TS_TSANDADDR) {
511 /* XXX - check whether it goes past end of packet */
513 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, optlen,
514 "(suboption would go past end of option)");
517 memcpy((char *)&addr, (char *)opd, sizeof(addr));
522 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 8,
523 "Address = %s, time stamp = %u",
524 ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
529 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, optlen,
530 "(suboption would go past end of option)");
533 /* XXX - check whether it goes past end of packet */
537 proto_tree_add_text(field_tree, NullTVB, offset + optoffset, 4,
538 "Time stamp = %u", ts);
544 static const ip_tcp_opt ipopts[] = {
567 dissect_ipopt_security
571 "Strict source route",
572 &ett_ip_option_route,
579 "Loose source route",
580 &ett_ip_option_route,
588 &ett_ip_option_route,
604 &ett_ip_option_timestamp,
606 IPOLEN_TIMESTAMP_MIN,
607 dissect_ipopt_timestamp
611 #define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
613 /* Dissect the IP or TCP options in a packet. */
615 dissect_ip_tcp_options(const u_char *opd, int offset, guint length,
616 const ip_tcp_opt *opttab, int nopts, int eol,
617 proto_tree *opt_tree)
620 const ip_tcp_opt *optp;
621 opt_len_type len_type;
624 char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
625 void (*dissect)(const struct ip_tcp_opt *, const u_char *,
626 int, guint, proto_tree *);
631 for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
632 if (optp->optcode == opt)
635 if (optp == &opttab[nopts]) {
636 /* We assume that the only NO_LENGTH options are EOL and NOP options,
637 so that we can treat unknown options as VARIABLE_LENGTH with a
638 minimum of 2, and at least be able to move on to the next option
639 by using the length in the option. */
640 optp = NULL; /* indicate that we don't know this option */
641 len_type = VARIABLE_LENGTH;
643 snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
647 len_type = optp->len_type;
648 optlen = optp->optlen;
650 dissect = optp->dissect;
652 --length; /* account for type byte */
653 if (len_type != NO_LENGTH) {
654 /* Option has a length. Is it in the packet? */
656 /* Bogus - packet must at least include option code byte and
658 proto_tree_add_text(opt_tree, NullTVB, offset, 1,
659 "%s (length byte past end of options)", name);
662 len = *opd++; /* total including type, len */
663 --length; /* account for length byte */
665 /* Bogus - option length is too short to include option code and
667 proto_tree_add_text(opt_tree, NullTVB, offset, 2,
668 "%s (with too-short option length = %u byte%s)", name,
669 len, plurality(len, "", "s"));
671 } else if (len - 2 > length) {
672 /* Bogus - option goes past the end of the header. */
673 proto_tree_add_text(opt_tree, NullTVB, offset, length,
674 "%s (option length = %u byte%s says option goes past end of options)",
675 name, len, plurality(len, "", "s"));
677 } else if (len_type == FIXED_LENGTH && len != optlen) {
678 /* Bogus - option length isn't what it's supposed to be for this
680 proto_tree_add_text(opt_tree, NullTVB, offset, len,
681 "%s (with option length = %u byte%s; should be %u)", name,
682 len, plurality(len, "", "s"), optlen);
684 } else if (len_type == VARIABLE_LENGTH && len < optlen) {
685 /* Bogus - option length is less than what it's supposed to be for
687 proto_tree_add_text(opt_tree, NullTVB, offset, len,
688 "%s (with option length = %u byte%s; should be >= %u)", name,
689 len, plurality(len, "", "s"), optlen);
693 proto_tree_add_text(opt_tree, NullTVB, offset, len, "%s (%u byte%s)",
694 name, len, plurality(len, "", "s"));
696 if (dissect != NULL) {
697 /* Option has a dissector. */
698 (*dissect)(optp, opd, offset, len, opt_tree);
700 /* Option has no data, hence no dissector. */
701 proto_tree_add_text(opt_tree, NullTVB, offset, len, "%s", name);
704 len -= 2; /* subtract size of type and length */
710 proto_tree_add_text(opt_tree, NullTVB, offset, 1, "%s", name);
718 static const value_string dscp_vals[] = {
719 { IPDSFIELD_DSCP_DEFAULT, "Default" },
720 { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
721 { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
722 { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
723 { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
724 { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
725 { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
726 { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
727 { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
728 { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
729 { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
730 { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
731 { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
732 { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
733 { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
734 { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
735 { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
736 { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
737 { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
738 { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
739 { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
742 static const value_string precedence_vals[] = {
743 { IPTOS_PREC_ROUTINE, "routine" },
744 { IPTOS_PREC_PRIORITY, "priority" },
745 { IPTOS_PREC_IMMEDIATE, "immediate" },
746 { IPTOS_PREC_FLASH, "flash" },
747 { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
748 { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
749 { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
750 { IPTOS_PREC_NETCONTROL, "network control" },
753 static const value_string iptos_vals[] = {
754 { IPTOS_NONE, "None" },
755 { IPTOS_LOWCOST, "Minimize cost" },
756 { IPTOS_RELIABILITY, "Maximize reliability" },
757 { IPTOS_THROUGHPUT, "Maximize throughput" },
758 { IPTOS_LOWDELAY, "Minimize delay" },
759 { IPTOS_SECURITY, "Maximize security" },
763 static const true_false_string tos_set_low = {
768 static const true_false_string tos_set_high = {
773 static const true_false_string flags_set_truth = {
778 static char *ip_checksum_state(e_ip *iph)
781 unsigned char *Ptr, *PtrEnd;
785 PtrEnd = (lo_nibble(iph->ip_v_hl) * 4 + (char *)iph);
786 for (Ptr = (unsigned char *) iph; Ptr < PtrEnd; Ptr += 2) {
787 memcpy(&word, Ptr, sizeof word);
791 Sum = (Sum & 0xFFFF) + (Sum >> 16);
792 Sum = (Sum & 0xFFFF) + (Sum >> 16);
801 dissect_ip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
803 proto_tree *ip_tree, *field_tree;
805 guint hlen, optlen, len;
809 /* To do: check for errs, etc. */
810 if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
811 dissect_data(pd, offset, fd, tree);
815 /* Avoids alignment problems on many architectures. */
816 memcpy(&iph, &pd[offset], sizeof(e_ip));
817 iph.ip_len = ntohs(iph.ip_len);
818 iph.ip_id = ntohs(iph.ip_id);
819 iph.ip_off = ntohs(iph.ip_off);
820 iph.ip_sum = ntohs(iph.ip_sum);
822 /* Length of IP datagram plus headers above it. */
823 len = iph.ip_len + offset;
825 /* Set the payload and captured-payload lengths to the minima of (the
826 IP length plus the length of the headers above it) and the frame
830 if (pi.captured_len > len)
831 pi.captured_len = len;
833 /* XXX - check to make sure this is at least IPH_MIN_LEN. */
834 hlen = lo_nibble(iph.ip_v_hl) * 4; /* IP header length, in bytes */
837 ti = proto_tree_add_item(tree, proto_ip, NullTVB, offset, hlen, FALSE);
838 ip_tree = proto_item_add_subtree(ti, ett_ip);
840 proto_tree_add_uint(ip_tree, hf_ip_version, NullTVB, offset, 1, hi_nibble(iph.ip_v_hl));
841 proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, NullTVB, offset, 1, hlen,
842 "Header length: %u bytes", hlen);
844 if (g_ip_dscp_actif) {
845 tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, NullTVB, offset + 1, 1, iph.ip_tos,
846 "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s)", iph.ip_tos,
847 IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
850 field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
851 proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, NullTVB, offset + 1, 1, iph.ip_tos);
852 proto_tree_add_uint(field_tree, hf_ip_dsfield_cu, NullTVB, offset + 1, 1, iph.ip_tos);
854 tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, NullTVB, offset + 1, 1, iph.ip_tos,
855 "Type of service: 0x%02x (%s)", iph.ip_tos,
856 val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
858 field_tree = proto_item_add_subtree(tf, ett_ip_tos);
859 proto_tree_add_uint(field_tree, hf_ip_tos_precedence, NullTVB, offset + 1, 1, iph.ip_tos);
860 proto_tree_add_boolean(field_tree, hf_ip_tos_delay, NullTVB, offset + 1, 1, iph.ip_tos);
861 proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, NullTVB, offset + 1, 1, iph.ip_tos);
862 proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, NullTVB, offset + 1, 1, iph.ip_tos);
863 proto_tree_add_boolean(field_tree, hf_ip_tos_cost, NullTVB, offset + 1, 1, iph.ip_tos);
865 proto_tree_add_uint(ip_tree, hf_ip_len, NullTVB, offset + 2, 2, iph.ip_len);
866 proto_tree_add_uint(ip_tree, hf_ip_id, NullTVB, offset + 4, 2, iph.ip_id);
868 flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
869 tf = proto_tree_add_uint(ip_tree, hf_ip_flags, NullTVB, offset + 6, 1, flags);
870 field_tree = proto_item_add_subtree(tf, ett_ip_off);
871 proto_tree_add_boolean(field_tree, hf_ip_flags_df, NullTVB, offset + 6, 1, flags),
872 proto_tree_add_boolean(field_tree, hf_ip_flags_mf, NullTVB, offset + 6, 1, flags),
874 proto_tree_add_uint(ip_tree, hf_ip_frag_offset, NullTVB, offset + 6, 2,
875 (iph.ip_off & IP_OFFSET)*8);
876 proto_tree_add_uint(ip_tree, hf_ip_ttl, NullTVB, offset + 8, 1, iph.ip_ttl);
877 proto_tree_add_uint_format(ip_tree, hf_ip_proto, NullTVB, offset + 9, 1, iph.ip_p,
878 "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
879 proto_tree_add_uint_format(ip_tree, hf_ip_checksum, NullTVB, offset + 10, 2, iph.ip_sum,
880 "Header checksum: 0x%04x (%s)", iph.ip_sum, ip_checksum_state((e_ip*) &pd[offset]));
881 proto_tree_add_ipv4(ip_tree, hf_ip_src, NullTVB, offset + 12, 4, iph.ip_src);
882 proto_tree_add_ipv4(ip_tree, hf_ip_dst, NullTVB, offset + 16, 4, iph.ip_dst);
883 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, NullTVB, offset + 12, 4, iph.ip_src);
884 proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, NullTVB, offset + 16, 4, iph.ip_dst);
886 /* Decode IP options, if any. */
887 if (hlen > sizeof (e_ip)) {
888 /* There's more than just the fixed-length header. Decode the
890 optlen = hlen - sizeof (e_ip); /* length of options, in bytes */
891 tf = proto_tree_add_text(ip_tree, NullTVB, offset + 20, optlen,
892 "Options: (%u bytes)", optlen);
893 field_tree = proto_item_add_subtree(tf, ett_ip_options);
894 dissect_ip_tcp_options(&pd[offset + 20], offset + 20, optlen,
895 ipopts, N_IP_OPTS, IPOPT_END, field_tree);
899 pi.ipproto = iph.ip_p;
900 pi.iplen = iph.ip_len;
901 pi.iphdrlen = lo_nibble(iph.ip_v_hl);
902 SET_ADDRESS(&pi.net_src, AT_IPv4, 4, &pd[offset + IPH_SRC]);
903 SET_ADDRESS(&pi.src, AT_IPv4, 4, &pd[offset + IPH_SRC]);
904 SET_ADDRESS(&pi.net_dst, AT_IPv4, 4, &pd[offset + IPH_DST]);
905 SET_ADDRESS(&pi.dst, AT_IPv4, 4, &pd[offset + IPH_DST]);
907 /* Skip over header + options */
910 if (iph.ip_off & IP_OFFSET) {
912 if (check_col(fd, COL_PROTOCOL))
913 col_add_str(fd, COL_PROTOCOL, "IP");
914 if (check_col(fd, COL_INFO))
915 col_add_fstr(fd, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
916 ipprotostr(iph.ip_p), iph.ip_p, (iph.ip_off & IP_OFFSET) * 8);
917 dissect_data(pd, offset, fd, tree);
921 /* do lookup with the subdissector table */
922 if (!dissector_try_port(ip_dissector_table, nxt, pd, offset, fd, tree)) {
923 /* Unknown protocol */
924 if (check_col(fd, COL_PROTOCOL))
925 col_add_str(fd, COL_PROTOCOL, "IP");
926 if (check_col(fd, COL_INFO))
927 col_add_fstr(fd, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
928 dissect_data(pd, offset, fd, tree);
933 static const gchar *unreach_str[] = {"Network unreachable",
935 "Protocol unreachable",
937 "Fragmentation needed",
938 "Source route failed",
939 "Destination network unknown",
940 "Destination host unknown",
941 "Source host isolated",
942 "Network administratively prohibited",
943 "Host administratively prohibited",
944 "Network unreachable for TOS",
945 "Host unreachable for TOS",
946 "Communication administratively filtered",
947 "Host precedence violation",
948 "Precedence cutoff in effect"};
950 #define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
952 static const gchar *redir_str[] = {"Redirect for network",
954 "Redirect for TOS and network",
955 "Redirect for TOS and host"};
957 #define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
959 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
960 "TTL equals 0 during reassembly"};
962 #define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
964 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
966 #define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
969 dissect_icmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
971 proto_tree *icmp_tree;
974 gchar type_str[64], code_str[64] = "";
975 guint8 num_addrs = 0;
976 guint8 addr_entry_size = 0;
979 /* Avoids alignment problems on many architectures. */
980 memcpy(&ih, &pd[offset], sizeof(e_icmp));
981 /* To do: check for runts, errs, etc. */
982 cksum = ntohs(ih.icmp_cksum);
984 switch (ih.icmp_type) {
986 strcpy(type_str, "Echo (ping) reply");
989 strcpy(type_str, "Destination unreachable");
990 if (ih.icmp_code < N_UNREACH) {
991 sprintf(code_str, "(%s)", unreach_str[ih.icmp_code]);
993 strcpy(code_str, "(Unknown - error?)");
996 case ICMP_SOURCEQUENCH:
997 strcpy(type_str, "Source quench (flow control)");
1000 strcpy(type_str, "Redirect");
1001 if (ih.icmp_code < N_REDIRECT) {
1002 sprintf(code_str, "(%s)", redir_str[ih.icmp_code]);
1004 strcpy(code_str, "(Unknown - error?)");
1008 strcpy(type_str, "Echo (ping) request");
1010 case ICMP_RTRADVERT:
1011 strcpy(type_str, "Router advertisement");
1013 case ICMP_RTRSOLICIT:
1014 strcpy(type_str, "Router solicitation");
1017 strcpy(type_str, "Time-to-live exceeded");
1018 if (ih.icmp_code < N_TIMXCEED) {
1019 sprintf(code_str, "(%s)", ttl_str[ih.icmp_code]);
1021 strcpy(code_str, "(Unknown - error?)");
1024 case ICMP_PARAMPROB:
1025 strcpy(type_str, "Parameter problem");
1026 if (ih.icmp_code < N_PARAMPROB) {
1027 sprintf(code_str, "(%s)", par_str[ih.icmp_code]);
1029 strcpy(code_str, "(Unknown - error?)");
1033 strcpy(type_str, "Timestamp request");
1035 case ICMP_TSTAMPREPLY:
1036 strcpy(type_str, "Timestamp reply");
1039 strcpy(type_str, "Information request");
1041 case ICMP_IREQREPLY:
1042 strcpy(type_str, "Information reply");
1045 strcpy(type_str, "Address mask request");
1047 case ICMP_MASKREPLY:
1048 strcpy(type_str, "Address mask reply");
1051 strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1054 if (check_col(fd, COL_PROTOCOL))
1055 col_add_str(fd, COL_PROTOCOL, "ICMP");
1056 if (check_col(fd, COL_INFO))
1057 col_add_str(fd, COL_INFO, type_str);
1060 ti = proto_tree_add_item(tree, proto_icmp, NullTVB, offset, 4, FALSE);
1061 icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1062 proto_tree_add_uint_format(icmp_tree, hf_icmp_type, NullTVB, offset, 1,
1065 ih.icmp_type, type_str);
1066 proto_tree_add_uint_format(icmp_tree, hf_icmp_code, NullTVB, offset + 1, 1,
1069 ih.icmp_code, code_str);
1070 proto_tree_add_uint(icmp_tree, hf_icmp_checksum, NullTVB, offset + 2, 2,
1073 /* Decode the second 4 bytes of the packet. */
1074 switch (ih.icmp_type) {
1075 case ICMP_ECHOREPLY:
1078 case ICMP_TSTAMPREPLY:
1080 case ICMP_IREQREPLY:
1082 case ICMP_MASKREPLY:
1083 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 2, "Identifier: 0x%04x",
1084 pntohs(&pd[offset + 4]));
1085 proto_tree_add_text(icmp_tree, NullTVB, offset + 6, 2, "Sequence number: %02x:%02x",
1086 pd[offset+6], pd[offset+7]);
1090 switch (ih.icmp_code) {
1091 case ICMP_FRAG_NEEDED:
1092 proto_tree_add_text(icmp_tree, NullTVB, offset + 6, 2, "MTU of next hop: %u",
1093 pntohs(&pd[offset + 6]));
1098 case ICMP_RTRADVERT:
1099 num_addrs = pd[offset + 4];
1100 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 1, "Number of addresses: %u",
1102 addr_entry_size = pd[offset + 5];
1103 proto_tree_add_text(icmp_tree, NullTVB, offset + 5, 1, "Address entry size: %u",
1105 proto_tree_add_text(icmp_tree, NullTVB, offset + 6, 2, "Lifetime: %s",
1106 time_secs_to_str(pntohs(&pd[offset + 6])));
1109 case ICMP_PARAMPROB:
1110 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 1, "Pointer: %u",
1115 proto_tree_add_text(icmp_tree, NullTVB, offset + 4, 4, "Gateway address: %s",
1116 ip_to_str((guint8 *)&pd[offset + 4]));
1120 /* Decode the additional information in the packet. */
1121 switch (ih.icmp_type) {
1124 case ICMP_PARAMPROB:
1125 case ICMP_SOURCEQUENCH:
1127 /* Decode the IP header and first 64 bits of data from the
1130 XXX - for now, just display it as data; not all dissection
1131 routines can handle a short packet without exploding. */
1132 dissect_data(pd, offset + 8, fd, icmp_tree);
1135 case ICMP_ECHOREPLY:
1137 dissect_data(pd, offset + 8, fd, icmp_tree);
1140 case ICMP_RTRADVERT:
1141 if (addr_entry_size == 2) {
1142 for (i = 0; i < num_addrs; i++) {
1143 proto_tree_add_text(icmp_tree, NullTVB, offset + 8 + (i*8), 4,
1144 "Router address: %s",
1145 ip_to_str((guint8 *)&pd[offset + 8 + (i*8)]));
1146 proto_tree_add_text(icmp_tree, NullTVB, offset + 12 + (i*8), 4,
1147 "Preference level: %u", pntohl(&pd[offset + 12 + (i*8)]));
1150 dissect_data(pd, offset + 8, fd, icmp_tree);
1154 case ICMP_TSTAMPREPLY:
1155 proto_tree_add_text(icmp_tree, NullTVB, offset + 8, 4, "Originate timestamp: %u",
1156 pntohl(&pd[offset + 8]));
1157 proto_tree_add_text(icmp_tree, NullTVB, offset + 12, 4, "Receive timestamp: %u",
1158 pntohl(&pd[offset + 12]));
1159 proto_tree_add_text(icmp_tree, NullTVB, offset + 16, 4, "Transmit timestamp: %u",
1160 pntohl(&pd[offset + 16]));
1164 case ICMP_MASKREPLY:
1165 proto_tree_add_text(icmp_tree, NullTVB, offset + 8, 4, "Address mask: %s (0x%8x)",
1166 ip_to_str((guint8 *)&pd[offset + 8]), pntohl(&pd[offset + 8]));
1174 dissect_igmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1176 dissect_igmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1180 proto_tree *igmp_tree;
1183 packet_info *pinfo = π
1184 tvbuff_t *tvb = tvb_create_from_top(offset);
1186 pinfo->current_proto = "IGMP";
1187 if (check_col(pinfo->fd, COL_PROTOCOL))
1188 col_add_str(pinfo->fd, COL_PROTOCOL, "IGMP");
1190 /* Avoids alignment problems on many architectures. */
1191 memcpy(&ih, tvb_get_ptr(tvb, 0, sizeof(e_igmp)), sizeof(e_igmp));
1193 switch (lo_nibble(ih.igmp_v_t)) {
1195 type_str = "Router query";
1198 type_str = "Host response (v1)";
1200 case IGMP_V2_LV_GRP:
1201 type_str = "Leave group (v2)";
1210 type_str = "Host response (v2)";
1212 case IGMP_MTRC_RESP:
1213 type_str = "Traceroute response";
1216 type_str = "Traceroute message";
1219 type_str = "Unknown IGMP";
1222 if (check_col(pinfo->fd, COL_INFO))
1223 col_add_str(pinfo->fd, COL_INFO, type_str);
1225 ti = proto_tree_add_item(tree, proto_igmp, tvb, 0, 8, FALSE);
1226 igmp_tree = proto_item_add_subtree(ti, ett_igmp);
1227 proto_tree_add_uint(igmp_tree, hf_igmp_version, tvb, 0, 1,
1228 hi_nibble(ih.igmp_v_t));
1229 proto_tree_add_uint_format(igmp_tree, hf_igmp_type, tvb, 0 , 1,
1230 lo_nibble(ih.igmp_v_t),
1232 lo_nibble(ih.igmp_v_t), type_str);
1233 proto_tree_add_item(igmp_tree, hf_igmp_unused, tvb, 1, 1, FALSE);
1234 proto_tree_add_item(igmp_tree, hf_igmp_checksum, tvb, 2, 2, FALSE);
1235 proto_tree_add_ipv4(igmp_tree, hf_igmp_group, tvb, 4, 4, ih.igmp_gaddr);
1240 proto_register_igmp(void)
1242 static hf_register_info hf[] = {
1245 { "Version", "igmp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1249 { "Type", "igmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1253 { "Unused", "igmp.unused", FT_UINT8, BASE_HEX, NULL, 0x0,
1256 { &hf_igmp_checksum,
1257 { "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1261 { "Group address", "igmp.group", FT_IPv4, BASE_NONE, NULL, 0x0,
1264 static gint *ett[] = {
1268 proto_igmp = proto_register_protocol ("Internet Group Management Protocol", "igmp");
1269 proto_register_field_array(proto_igmp, hf, array_length(hf));
1270 proto_register_subtree_array(ett, array_length(ett));
1274 proto_reg_handoff_igmp(void)
1276 dissector_add("ip.proto", IP_PROTO_IGMP, dissect_igmp);
1280 proto_register_ip(void)
1282 static hf_register_info hf[] = {
1285 { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1289 { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1293 { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1296 { &hf_ip_dsfield_dscp,
1297 { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1298 VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1301 { &hf_ip_dsfield_cu,
1302 { "Currently Unused", "ip.dsfield.cu", FT_UINT8, BASE_DEC, NULL,
1307 { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1310 { &hf_ip_tos_precedence,
1311 { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1316 { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1320 { &hf_ip_tos_throughput,
1321 { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1325 { &hf_ip_tos_reliability,
1326 { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1331 { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1336 { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1340 { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1344 { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1348 { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1352 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1356 { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1360 { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1364 { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1367 { &hf_ip_frag_offset,
1368 { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1372 { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1376 { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1380 { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1383 static gint *ett[] = {
1390 &ett_ip_option_route,
1391 &ett_ip_option_timestamp,
1394 proto_ip = proto_register_protocol ("Internet Protocol", "ip");
1395 proto_register_field_array(proto_ip, hf, array_length(hf));
1396 proto_register_subtree_array(ett, array_length(ett));
1398 /* subdissector code */
1399 ip_dissector_table = register_dissector_table("ip.proto");
1403 proto_reg_handoff_ip(void)
1405 dissector_add("ethertype", ETHERTYPE_IP, dissect_ip);
1406 dissector_add("ppp.protocol", PPP_IP, dissect_ip);
1407 dissector_add("llc.dsap", SAP_IP, dissect_ip);
1408 dissector_add("ip.proto", IP_PROTO_IPV4, dissect_ip);
1409 dissector_add("ip.proto", IP_PROTO_IPIP, dissect_ip);
1413 proto_register_icmp(void)
1415 static hf_register_info hf[] = {
1418 { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1422 { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
1425 { &hf_icmp_checksum,
1426 { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1429 static gint *ett[] = {
1433 proto_icmp = proto_register_protocol ("Internet Control Message Protocol",
1435 proto_register_field_array(proto_icmp, hf, array_length(hf));
1436 proto_register_subtree_array(ett, array_length(ett));
1440 proto_reg_handoff_icmp(void)
1442 dissector_add("ip.proto", IP_PROTO_ICMP, dissect_icmp);