Give the code that computes protocol statistics a progress dialog box,
[obnox/wireshark/wip.git] / packet-ip.c
1 /* packet-ip.c
2  * Routines for IP and miscellaneous IP protocol packet disassembly
3  *
4  * $Id: packet-ip.c,v 1.127 2001/03/15 09:11:00 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
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.
15  * 
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.
20  * 
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.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
36 #endif
37
38 #include <stdio.h>
39 #include <string.h>
40 #include <glib.h>
41
42 #ifdef NEED_SNPRINTF_H
43 # include "snprintf.h"
44 #endif
45
46 #include "packet.h"
47 #include "resolv.h"
48 #include "prefs.h"
49 #include "etypes.h"
50 #include "greproto.h"
51 #include "ppptypes.h"
52 #include "llcsaps.h"
53 #include "aftypes.h"
54 #include "packet-ip.h"
55 #include "packet-ipsec.h"
56 #include "in_cksum.h"
57 #include "nlpid.h"
58
59 static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
60 static void dissect_igmp(tvbuff_t *, packet_info *, proto_tree *);
61
62 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
63 static gboolean g_ip_dscp_actif = TRUE;
64
65 static int proto_ip = -1;
66 static int hf_ip_version = -1;
67 static int hf_ip_hdr_len = -1;
68 static int hf_ip_dsfield = -1;
69 static int hf_ip_dsfield_dscp = -1;
70 static int hf_ip_dsfield_ect = -1;
71 static int hf_ip_dsfield_ce = -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;
90 static int hf_ip_checksum_bad = -1;
91
92 static gint ett_ip = -1;
93 static gint ett_ip_dsfield = -1;
94 static gint ett_ip_tos = -1;
95 static gint ett_ip_off = -1;
96 static gint ett_ip_options = -1;
97 static gint ett_ip_option_sec = -1;
98 static gint ett_ip_option_route = -1;
99 static gint ett_ip_option_timestamp = -1;
100
101 /* Used by IPv6 as well, so not static */
102 dissector_table_t ip_dissector_table;
103
104 static int proto_igmp = -1;
105 static int hf_igmp_version = -1;
106 static int hf_igmp_type = -1;
107 static int hf_igmp_unused = -1;
108 static int hf_igmp_checksum = -1;
109 static int hf_igmp_group = -1;
110
111 static gint ett_igmp = -1;
112
113 static int proto_icmp = -1;
114 static int hf_icmp_type = -1;
115 static int hf_icmp_code = -1;
116 static int hf_icmp_checksum = -1;
117 static int hf_icmp_checksum_bad = -1;
118
119 static gint ett_icmp = -1;
120
121 /* ICMP definitions */
122
123 #define ICMP_ECHOREPLY     0
124 #define ICMP_UNREACH       3
125 #define ICMP_SOURCEQUENCH  4
126 #define ICMP_REDIRECT      5
127 #define ICMP_ECHO          8
128 #define ICMP_RTRADVERT     9
129 #define ICMP_RTRSOLICIT   10
130 #define ICMP_TIMXCEED     11
131 #define ICMP_PARAMPROB    12
132 #define ICMP_TSTAMP       13
133 #define ICMP_TSTAMPREPLY  14
134 #define ICMP_IREQ         15
135 #define ICMP_IREQREPLY    16
136 #define ICMP_MASKREQ      17
137 #define ICMP_MASKREPLY    18
138
139 /* ICMP UNREACHABLE */
140
141 #define ICMP_NET_UNREACH        0       /* Network Unreachable */
142 #define ICMP_HOST_UNREACH       1       /* Host Unreachable */
143 #define ICMP_PROT_UNREACH       2       /* Protocol Unreachable */
144 #define ICMP_PORT_UNREACH       3       /* Port Unreachable */
145 #define ICMP_FRAG_NEEDED        4       /* Fragmentation Needed/DF set */
146 #define ICMP_SR_FAILED          5       /* Source Route failed */
147 #define ICMP_NET_UNKNOWN        6
148 #define ICMP_HOST_UNKNOWN       7
149 #define ICMP_HOST_ISOLATED      8
150 #define ICMP_NET_ANO            9
151 #define ICMP_HOST_ANO           10
152 #define ICMP_NET_UNR_TOS        11
153 #define ICMP_HOST_UNR_TOS       12
154 #define ICMP_PKT_FILTERED       13      /* Packet filtered */
155 #define ICMP_PREC_VIOLATION     14      /* Precedence violation */
156 #define ICMP_PREC_CUTOFF        15      /* Precedence cut off */
157
158
159 /* IGMP structs and definitions */
160 typedef struct _e_igmp {
161   guint8  igmp_v_t; /* combines igmp_v and igmp_t */
162   guint8  igmp_unused;
163   guint16 igmp_cksum;
164   guint32 igmp_gaddr;
165 } e_igmp;
166
167 #define IGMP_M_QRY     0x01
168 #define IGMP_V1_M_RPT  0x02
169 #define IGMP_V2_LV_GRP 0x07
170 #define IGMP_DVMRP     0x03
171 #define IGMP_PIM       0x04
172 #define IGMP_V2_M_RPT  0x06
173 #define IGMP_MTRC_RESP 0x1e
174 #define IGMP_MTRC      0x1f
175
176 /* IP structs and definitions */
177
178 typedef struct _e_ip 
179    {
180    guint8  ip_v_hl; /* combines ip_v and ip_hl */
181    guint8  ip_tos;
182    guint16 ip_len;
183    guint16 ip_id;
184    guint16 ip_off;
185    guint8  ip_ttl;
186    guint8  ip_p;
187    guint16 ip_sum;
188    guint32 ip_src;
189    guint32 ip_dst;
190    } e_ip;
191
192 /* Offsets of fields within an IP header. */
193 #define IPH_V_HL        0
194 #define IPH_TOS         1
195 #define IPH_LEN         2
196 #define IPH_ID          4
197 #define IPH_TTL         6
198 #define IPH_OFF         8
199 #define IPH_P           9
200 #define IPH_SUM         10
201 #define IPH_SRC         12
202 #define IPH_DST         16
203
204 /* Minimum IP header length. */
205 #define IPH_MIN_LEN     20
206
207 /* IP flags. */
208 #define IP_CE           0x8000          /* Flag: "Congestion"           */
209 #define IP_DF           0x4000          /* Flag: "Don't Fragment"       */
210 #define IP_MF           0x2000          /* Flag: "More Fragments"       */
211 #define IP_OFFSET       0x1FFF          /* "Fragment Offset" part       */
212
213 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
214 #define IPDSFIELD_DSCP_MASK     0xFC
215 #define IPDSFIELD_ECN_MASK     0x03
216 #define IPDSFIELD_DSCP_SHIFT    2
217 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
218 #define IPDSFIELD_ECN(dsfield)  ((dsfield)&IPDSFIELD_ECN_MASK)
219 #define IPDSFIELD_DSCP_DEFAULT  0x00
220 #define IPDSFIELD_DSCP_CS1      0x08
221 #define IPDSFIELD_DSCP_CS2      0x10
222 #define IPDSFIELD_DSCP_CS3      0x18
223 #define IPDSFIELD_DSCP_CS4      0x20
224 #define IPDSFIELD_DSCP_CS5      0x28
225 #define IPDSFIELD_DSCP_CS6      0x30
226 #define IPDSFIELD_DSCP_CS7      0x38
227 #define IPDSFIELD_DSCP_AF11     0x0A
228 #define IPDSFIELD_DSCP_AF12     0x0C
229 #define IPDSFIELD_DSCP_AF13     0x0E
230 #define IPDSFIELD_DSCP_AF21     0x12
231 #define IPDSFIELD_DSCP_AF22     0x14
232 #define IPDSFIELD_DSCP_AF23     0x16
233 #define IPDSFIELD_DSCP_AF31     0x1A
234 #define IPDSFIELD_DSCP_AF32     0x1C
235 #define IPDSFIELD_DSCP_AF33     0x1E
236 #define IPDSFIELD_DSCP_AF41     0x22
237 #define IPDSFIELD_DSCP_AF42     0x24
238 #define IPDSFIELD_DSCP_AF43     0x26
239 #define IPDSFIELD_DSCP_EF       0x2E
240 #define IPDSFIELD_ECT_MASK      0x02
241 #define IPDSFIELD_CE_MASK       0x01
242
243 /* IP TOS, superseded by the DS Field, RFC 2474. */
244 #define IPTOS_TOS_MASK    0x1E
245 #define IPTOS_TOS(tos)    ((tos) & IPTOS_TOS_MASK)
246 #define IPTOS_NONE        0x00
247 #define IPTOS_LOWCOST     0x02
248 #define IPTOS_RELIABILITY 0x04
249 #define IPTOS_THROUGHPUT  0x08
250 #define IPTOS_LOWDELAY    0x10
251 #define IPTOS_SECURITY    0x1E
252
253 #define IPTOS_PREC_MASK         0xE0
254 #define IPTOS_PREC_SHIFT        5
255 #define IPTOS_PREC(tos)         (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
256 #define IPTOS_PREC_NETCONTROL           7
257 #define IPTOS_PREC_INTERNETCONTROL      6
258 #define IPTOS_PREC_CRITIC_ECP           5
259 #define IPTOS_PREC_FLASHOVERRIDE        4
260 #define IPTOS_PREC_FLASH                3
261 #define IPTOS_PREC_IMMEDIATE            2
262 #define IPTOS_PREC_PRIORITY             1
263 #define IPTOS_PREC_ROUTINE              0
264
265 /* IP options */
266 #define IPOPT_COPY              0x80
267
268 #define IPOPT_CONTROL           0x00
269 #define IPOPT_RESERVED1         0x20
270 #define IPOPT_MEASUREMENT       0x40
271 #define IPOPT_RESERVED2         0x60
272
273 #define IPOPT_END       (0 |IPOPT_CONTROL)
274 #define IPOPT_NOOP      (1 |IPOPT_CONTROL)
275 #define IPOPT_SEC       (2 |IPOPT_CONTROL|IPOPT_COPY)
276 #define IPOPT_LSRR      (3 |IPOPT_CONTROL|IPOPT_COPY)
277 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
278 #define IPOPT_RR        (7 |IPOPT_CONTROL)
279 #define IPOPT_SID       (8 |IPOPT_CONTROL|IPOPT_COPY)
280 #define IPOPT_SSRR      (9 |IPOPT_CONTROL|IPOPT_COPY)
281 #define IPOPT_RA        (20|IPOPT_CONTROL|IPOPT_COPY)
282
283 /* IP option lengths */
284 #define IPOLEN_SEC      11
285 #define IPOLEN_LSRR_MIN 3
286 #define IPOLEN_TIMESTAMP_MIN 5
287 #define IPOLEN_RR_MIN   3
288 #define IPOLEN_SID      4
289 #define IPOLEN_SSRR_MIN 3
290 #define IPOLEN_RA       4
291
292 #define IPSEC_UNCLASSIFIED      0x0000
293 #define IPSEC_CONFIDENTIAL      0xF135
294 #define IPSEC_EFTO              0x789A
295 #define IPSEC_MMMM              0xBC4D
296 #define IPSEC_RESTRICTED        0xAF13
297 #define IPSEC_SECRET            0xD788
298 #define IPSEC_TOPSECRET         0x6BC5
299 #define IPSEC_RESERVED1         0x35E2
300 #define IPSEC_RESERVED2         0x9AF1
301 #define IPSEC_RESERVED3         0x4D78
302 #define IPSEC_RESERVED4         0x24BD
303 #define IPSEC_RESERVED5         0x135E
304 #define IPSEC_RESERVED6         0x89AF
305 #define IPSEC_RESERVED7         0xC4D6
306 #define IPSEC_RESERVED8         0xE26B
307
308 #define IPOPT_TS_TSONLY         0               /* timestamps only */
309 #define IPOPT_TS_TSANDADDR      1               /* timestamps and addresses */
310 #define IPOPT_TS_PRESPEC        3               /* specified modules only */
311
312
313 void
314 capture_ip(const u_char *pd, int offset, packet_counts *ld) {
315   if (!BYTES_ARE_IN_FRAME(offset, IPH_MIN_LEN)) {
316     ld->other++;
317     return;
318   }
319   switch (pd[offset + 9]) {
320     case IP_PROTO_SCTP:
321       ld->sctp++;
322       break;
323     case IP_PROTO_TCP:
324       ld->tcp++;
325       break;
326     case IP_PROTO_UDP:
327       ld->udp++;
328       break;
329     case IP_PROTO_ICMP:
330       ld->icmp++;
331       break;
332     case IP_PROTO_OSPF:
333       ld->ospf++;
334       break;
335     case IP_PROTO_GRE:
336       ld->gre++;
337       break;
338     case IP_PROTO_VINES:
339       ld->vines++;
340       break;
341     default:
342       ld->other++;
343   }
344 }
345
346 static void
347 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
348                         guint optlen, frame_data *fd, proto_tree *opt_tree)
349 {
350   proto_tree *field_tree = NULL;
351   proto_item *tf;
352   guint      val;
353   static const value_string secl_vals[] = {
354     {IPSEC_UNCLASSIFIED, "Unclassified"},
355     {IPSEC_CONFIDENTIAL, "Confidential"},
356     {IPSEC_EFTO,         "EFTO"        },
357     {IPSEC_MMMM,         "MMMM"        },
358     {IPSEC_RESTRICTED,   "Restricted"  },
359     {IPSEC_SECRET,       "Secret"      },
360     {IPSEC_TOPSECRET,    "Top secret"  },
361     {IPSEC_RESERVED1,    "Reserved"    },
362     {IPSEC_RESERVED2,    "Reserved"    },
363     {IPSEC_RESERVED3,    "Reserved"    },
364     {IPSEC_RESERVED4,    "Reserved"    },
365     {IPSEC_RESERVED5,    "Reserved"    },
366     {IPSEC_RESERVED6,    "Reserved"    },
367     {IPSEC_RESERVED7,    "Reserved"    },
368     {IPSEC_RESERVED8,    "Reserved"    },
369     {0,                  NULL          } };
370
371   tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s:", optp->name);
372   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
373   offset += 2;
374
375   val = tvb_get_ntohs(tvb, offset);
376   proto_tree_add_text(field_tree, tvb, offset,       2,
377               "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
378   offset += 2;
379
380   val = tvb_get_ntohs(tvb, offset);
381   proto_tree_add_text(field_tree, tvb, offset,         2,
382               "Compartments: %u", val);
383   offset += 2;
384
385   proto_tree_add_text(field_tree, tvb, offset,         2,
386               "Handling restrictions: %c%c",
387               tvb_get_guint8(tvb, offset),
388               tvb_get_guint8(tvb, offset + 1));
389   offset += 2;
390
391   proto_tree_add_text(field_tree, tvb, offset,         3,
392               "Transmission control code: %c%c%c",
393               tvb_get_guint8(tvb, offset),
394               tvb_get_guint8(tvb, offset + 1),
395               tvb_get_guint8(tvb, offset + 2));
396 }
397
398 static void
399 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
400                         guint optlen, frame_data *fd, proto_tree *opt_tree)
401 {
402   proto_tree *field_tree = NULL;
403   proto_item *tf;
404   int ptr;
405   int optoffset = 0;
406   struct in_addr addr;
407
408   tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s (%u bytes)",
409                                 optp->name, optlen);
410   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
411
412   optoffset += 2;       /* skip past type and length */
413   optlen -= 2;          /* subtract size of type and length */
414
415   ptr = tvb_get_guint8(tvb, offset + optoffset);
416   proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
417               "Pointer: %d%s", ptr,
418               ((ptr < 4) ? " (points before first address)" :
419                ((ptr & 3) ? " (points to middle of address)" : "")));
420   optoffset++;
421   optlen--;
422   ptr--;        /* ptr is 1-origin */
423
424   while (optlen > 0) {
425     if (optlen < 4) {
426       proto_tree_add_text(field_tree, tvb, offset,      optlen,
427         "(suboption would go past end of option)");
428       break;
429     }
430
431     /* Avoids alignment problems on many architectures. */
432     tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
433
434     proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
435               "%s%s",
436               ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
437               ((optoffset == ptr) ? " <- (current)" : ""));
438     optoffset += 4;
439     optlen -= 4;
440   }
441 }
442
443 static void
444 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
445                         guint optlen, frame_data *fd, proto_tree *opt_tree)
446 {
447   proto_tree_add_text(opt_tree, tvb, offset,      optlen,
448     "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
449   return;
450 }
451
452 static void
453 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
454     int offset, guint optlen, frame_data *fd, proto_tree *opt_tree)
455 {
456   proto_tree *field_tree = NULL;
457   proto_item *tf;
458   int        ptr;
459   int        optoffset = 0;
460   int        flg;
461   static const value_string flag_vals[] = {
462     {IPOPT_TS_TSONLY,    "Time stamps only"                      },
463     {IPOPT_TS_TSANDADDR, "Time stamp and address"                },
464     {IPOPT_TS_PRESPEC,   "Time stamps for prespecified addresses"},
465     {0,                  NULL                                    } };
466   struct in_addr addr;
467   guint ts;
468
469   tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s:", optp->name);
470   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
471
472   optoffset += 2;       /* skip past type and length */
473   optlen -= 2;          /* subtract size of type and length */
474
475   ptr = tvb_get_guint8(tvb, offset + optoffset);
476   proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
477               "Pointer: %d%s", ptr,
478               ((ptr < 5) ? " (points before first address)" :
479                (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
480   optoffset++;
481   optlen--;
482   ptr--;        /* ptr is 1-origin */
483
484   flg = tvb_get_guint8(tvb, offset + optoffset);
485   proto_tree_add_text(field_tree, tvb, offset + optoffset,   1,
486         "Overflow: %u", flg >> 4);
487   flg &= 0xF;
488   proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
489         "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
490   optoffset++;
491   optlen--;
492
493   while (optlen > 0) {
494     if (flg == IPOPT_TS_TSANDADDR) {
495       if (optlen < 8) {
496         proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
497           "(suboption would go past end of option)");
498         break;
499       }
500       tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
501       ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
502       optlen -= 8;
503       proto_tree_add_text(field_tree, tvb, offset + optoffset,      8,
504           "Address = %s, time stamp = %u",
505           ((addr.s_addr == 0) ? "-" :  (char *)get_hostname(addr.s_addr)),
506           ts);
507       optoffset += 8;
508     } else {
509       if (optlen < 4) {
510         proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
511           "(suboption would go past end of option)");
512         break;
513       }
514       ts = tvb_get_ntohl(tvb, offset + optoffset);
515       optlen -= 4;
516       proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
517           "Time stamp = %u", ts);
518       optoffset += 4;
519     }
520   }
521 }
522
523 static void
524 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
525                 guint optlen, frame_data *fd, proto_tree *opt_tree)
526 {
527   /* Router-Alert, as defined by RFC2113 */
528   int opt = tvb_get_ntohs(tvb, offset + 2);
529   static const value_string ra_opts[] = { 
530         {0, "Every router examines packet"},
531         {0, NULL}
532   };
533   
534   proto_tree_add_text(opt_tree, tvb, offset,      optlen,
535     "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
536   return;
537 }
538
539 static const ip_tcp_opt ipopts[] = {
540   {
541     IPOPT_END,
542     "EOL",
543     NULL,
544     NO_LENGTH,
545     0,
546     NULL,
547   },
548   {
549     IPOPT_NOOP,
550     "NOP",
551     NULL,
552     NO_LENGTH,
553     0,
554     NULL,
555   },
556   {
557     IPOPT_SEC,
558     "Security",
559     &ett_ip_option_sec,
560     FIXED_LENGTH,
561     IPOLEN_SEC,
562     dissect_ipopt_security
563   },
564   {
565     IPOPT_SSRR,
566     "Strict source route",
567     &ett_ip_option_route,
568     VARIABLE_LENGTH,
569     IPOLEN_SSRR_MIN,
570     dissect_ipopt_route
571   },
572   {
573     IPOPT_LSRR,
574     "Loose source route",
575     &ett_ip_option_route,
576     VARIABLE_LENGTH,
577     IPOLEN_LSRR_MIN,
578     dissect_ipopt_route
579   },
580   {
581     IPOPT_RR,
582     "Record route",
583     &ett_ip_option_route,
584     VARIABLE_LENGTH,
585     IPOLEN_RR_MIN,
586     dissect_ipopt_route
587   },
588   {
589     IPOPT_SID,
590     "Stream identifier",
591     NULL,
592     FIXED_LENGTH,
593     IPOLEN_SID,
594     dissect_ipopt_sid
595   },
596   {
597     IPOPT_TIMESTAMP,
598     "Time stamp",
599     &ett_ip_option_timestamp,
600     VARIABLE_LENGTH,
601     IPOLEN_TIMESTAMP_MIN,
602     dissect_ipopt_timestamp
603   },
604   {
605     IPOPT_RA,
606     "Router Alert",
607     NULL,
608     FIXED_LENGTH,
609     IPOLEN_RA,
610     dissect_ipopt_ra
611   },
612 };
613
614 #define N_IP_OPTS       (sizeof ipopts / sizeof ipopts[0])
615
616 /* Dissect the IP or TCP options in a packet. */
617 void
618 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
619                         const ip_tcp_opt *opttab, int nopts, int eol,
620                         frame_data *fd, proto_tree *opt_tree)
621 {
622   u_char            opt;
623   const ip_tcp_opt *optp;
624   opt_len_type      len_type;
625   int               optlen;
626   char             *name;
627   char              name_str[7+1+1+2+2+1+1];    /* "Unknown (0x%02x)" */
628   void            (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
629                                 int, guint, frame_data *, proto_tree *);
630   guint             len;
631
632   while (length > 0) {
633     opt = tvb_get_guint8(tvb, offset);
634     for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
635       if (optp->optcode == opt)
636         break;
637     }
638     if (optp == &opttab[nopts]) {
639       /* We assume that the only NO_LENGTH options are EOL and NOP options,
640          so that we can treat unknown options as VARIABLE_LENGTH with a
641          minimum of 2, and at least be able to move on to the next option
642          by using the length in the option. */
643       optp = NULL;      /* indicate that we don't know this option */
644       len_type = VARIABLE_LENGTH;
645       optlen = 2;
646       snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
647       name = name_str;
648       dissect = NULL;
649     } else {
650       len_type = optp->len_type;
651       optlen = optp->optlen;
652       name = optp->name;
653       dissect = optp->dissect;
654     }
655     --length;      /* account for type byte */
656     if (len_type != NO_LENGTH) {
657       /* Option has a length. Is it in the packet? */
658       if (length == 0) {
659         /* Bogus - packet must at least include option code byte and
660            length byte! */
661         proto_tree_add_text(opt_tree, tvb, offset,      1,
662               "%s (length byte past end of options)", name);
663         return;
664       }
665       len = tvb_get_guint8(tvb, offset + 1);  /* total including type, len */
666       --length;    /* account for length byte */
667       if (len < 2) {
668         /* Bogus - option length is too short to include option code and
669            option length. */
670         proto_tree_add_text(opt_tree, tvb, offset,      2,
671               "%s (with too-short option length = %u byte%s)", name,
672               len, plurality(len, "", "s"));
673         return;
674       } else if (len - 2 > length) {
675         /* Bogus - option goes past the end of the header. */
676         proto_tree_add_text(opt_tree, tvb, offset,      length,
677               "%s (option length = %u byte%s says option goes past end of options)",
678               name, len, plurality(len, "", "s"));
679         return;
680       } else if (len_type == FIXED_LENGTH && len != optlen) {
681         /* Bogus - option length isn't what it's supposed to be for this
682            option. */
683         proto_tree_add_text(opt_tree, tvb, offset,      len,
684               "%s (with option length = %u byte%s; should be %u)", name,
685               len, plurality(len, "", "s"), optlen);
686         return;
687       } else if (len_type == VARIABLE_LENGTH && len < optlen) {
688         /* Bogus - option length is less than what it's supposed to be for
689            this option. */
690         proto_tree_add_text(opt_tree, tvb, offset,      len,
691               "%s (with option length = %u byte%s; should be >= %u)", name,
692               len, plurality(len, "", "s"), optlen);
693         return;
694       } else {
695         if (optp == NULL) {
696           proto_tree_add_text(opt_tree, tvb, offset,    len, "%s (%u byte%s)",
697                                 name, len, plurality(len, "", "s"));
698         } else {
699           if (dissect != NULL) {
700             /* Option has a dissector. */
701             (*dissect)(optp, tvb, offset,          len, fd, opt_tree);
702           } else {
703             /* Option has no data, hence no dissector. */
704             proto_tree_add_text(opt_tree, tvb, offset,  len, "%s", name);
705           }
706         }
707         len -= 2;       /* subtract size of type and length */
708         offset += 2 + len;
709       }
710       length -= len;
711     } else {
712       proto_tree_add_text(opt_tree, tvb, offset,      1, "%s", name);
713       offset += 1;
714     }
715     if (opt == eol)
716       break;
717   }
718 }
719
720 static const value_string dscp_vals[] = {
721                   { IPDSFIELD_DSCP_DEFAULT, "Default"               },
722                   { IPDSFIELD_DSCP_CS1,     "Class Selector 1"      },
723                   { IPDSFIELD_DSCP_CS2,     "Class Selector 2"      },
724                   { IPDSFIELD_DSCP_CS3,     "Class Selector 3"      },
725                   { IPDSFIELD_DSCP_CS4,     "Class Selector 4"      },
726                   { IPDSFIELD_DSCP_CS5,     "Class Selector 5"      },
727                   { IPDSFIELD_DSCP_CS6,     "Class Selector 6"      },
728                   { IPDSFIELD_DSCP_CS7,     "Class Selector 7"      },
729                   { IPDSFIELD_DSCP_AF11,    "Assured Forwarding 11" },
730                   { IPDSFIELD_DSCP_AF12,    "Assured Forwarding 12" },
731                   { IPDSFIELD_DSCP_AF13,    "Assured Forwarding 13" },
732                   { IPDSFIELD_DSCP_AF21,    "Assured Forwarding 21" },
733                   { IPDSFIELD_DSCP_AF22,    "Assured Forwarding 22" },
734                   { IPDSFIELD_DSCP_AF23,    "Assured Forwarding 23" },
735                   { IPDSFIELD_DSCP_AF31,    "Assured Forwarding 31" },
736                   { IPDSFIELD_DSCP_AF32,    "Assured Forwarding 32" },
737                   { IPDSFIELD_DSCP_AF33,    "Assured Forwarding 33" },
738                   { IPDSFIELD_DSCP_AF41,    "Assured Forwarding 41" },
739                   { IPDSFIELD_DSCP_AF42,    "Assured Forwarding 42" },
740                   { IPDSFIELD_DSCP_AF43,    "Assured Forwarding 43" },
741                   { IPDSFIELD_DSCP_EF,      "Expedited Forwarding"  },
742                   { 0,                      NULL                    } };
743
744 static const value_string precedence_vals[] = {
745                   { IPTOS_PREC_ROUTINE,         "routine"              },
746                   { IPTOS_PREC_PRIORITY,        "priority"             },
747                   { IPTOS_PREC_IMMEDIATE,       "immediate"            },
748                   { IPTOS_PREC_FLASH,           "flash"                },
749                   { IPTOS_PREC_FLASHOVERRIDE,   "flash override"       },
750                   { IPTOS_PREC_CRITIC_ECP,      "CRITIC/ECP"           },
751                   { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
752                   { IPTOS_PREC_NETCONTROL,      "network control"      },
753                   { 0,                          NULL                   } };
754
755 static const value_string iptos_vals[] = {
756         { IPTOS_NONE,           "None" },
757         { IPTOS_LOWCOST,        "Minimize cost" },
758         { IPTOS_RELIABILITY,    "Maximize reliability" },
759         { IPTOS_THROUGHPUT,     "Maximize throughput" },
760         { IPTOS_LOWDELAY,       "Minimize delay" },
761         { IPTOS_SECURITY,       "Maximize security" },
762         { 0,                    NULL }
763 };
764
765 static const true_false_string tos_set_low = {
766   "Low",
767   "Normal"
768 };
769
770 static const true_false_string tos_set_high = {
771   "High",
772   "Normal"
773 };
774
775 static const true_false_string flags_set_truth = {
776   "Set",
777   "Not set"
778 };
779
780 static guint16 ip_checksum(const guint8 *ptr, int len)
781 {
782         vec_t cksum_vec[1];
783
784         cksum_vec[0].ptr = ptr;
785         cksum_vec[0].len = len;
786         return in_cksum(&cksum_vec[0], 1);
787 }
788
789 static void
790 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
791 {
792   e_ip       iph;
793   proto_tree *ip_tree, *field_tree;
794   proto_item *ti, *tf;
795   int        offset = 0;
796   guint      hlen, optlen, len, payload_len, reported_payload_len, padding;
797   guint16    flags;
798   guint8     nxt;
799   guint16    ipsum;
800   tvbuff_t   *next_tvb;
801
802   if (check_col(pinfo->fd, COL_PROTOCOL))
803     col_set_str(pinfo->fd, COL_PROTOCOL, "IP");
804   if (check_col(pinfo->fd, COL_INFO))
805     col_clear(pinfo->fd, COL_INFO);
806
807   /* Avoids alignment problems on many architectures. */
808   tvb_memcpy(tvb, (guint8 *)&iph, offset, sizeof(e_ip));
809   iph.ip_len = ntohs(iph.ip_len);
810   iph.ip_id  = ntohs(iph.ip_id);
811   iph.ip_off = ntohs(iph.ip_off);
812   iph.ip_sum = ntohs(iph.ip_sum);
813
814   /* Length of payload handed to us. */
815   reported_payload_len = tvb_reported_length(tvb);
816   payload_len = tvb_length(tvb);
817
818   /* Length of IP datagram. */
819   len = iph.ip_len;
820
821   if (len < reported_payload_len) {
822     /* Adjust the length of this tvbuff to include only the IP datagram.
823        Our caller may use that to determine how much of its packet
824        was padding. */
825     tvb_set_reported_length(tvb, len);
826
827     /* Shrink the total payload by the amount of padding. */
828     padding = reported_payload_len - len;
829     if (pinfo->len >= padding)
830       pinfo->len -= padding;
831
832     /* Shrink the captured payload by the amount of padding in the
833        captured payload (which may be less than the amount of padding,
834        as the padding may not have been captured). */
835     if (len < payload_len) {
836       padding = payload_len - len;
837       if (pinfo->captured_len >= padding)
838         pinfo->captured_len -= padding;
839     }
840   }
841
842   /* XXX - check to make sure this is at least IPH_MIN_LEN. */
843   hlen = lo_nibble(iph.ip_v_hl) * 4;    /* IP header length, in bytes */
844   
845   if (tree) {
846     ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
847     ip_tree = proto_item_add_subtree(ti, ett_ip);
848
849     proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1, hi_nibble(iph.ip_v_hl));
850     proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
851         "Header length: %u bytes", hlen);
852
853     if (g_ip_dscp_actif) {
854       tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph.ip_tos,
855            "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph.ip_tos,
856            IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
857            "Unknown DSCP"),IPDSFIELD_ECN(iph.ip_tos));
858
859       field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
860       proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph.ip_tos);
861       proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph.ip_tos);
862       proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph.ip_tos);
863     } else {
864       tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph.ip_tos,
865           "Type of service: 0x%02x (%s)", iph.ip_tos,
866           val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
867
868       field_tree = proto_item_add_subtree(tf, ett_ip_tos);
869       proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph.ip_tos);
870       proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph.ip_tos);
871       proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph.ip_tos);
872       proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph.ip_tos);
873       proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph.ip_tos);
874     }
875     proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset +  2, 2, iph.ip_len);
876     proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset +  4, 2, iph.ip_id);
877
878     flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
879     tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset +  6, 1, flags);
880     field_tree = proto_item_add_subtree(tf, ett_ip_off);
881     proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
882     proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
883
884     proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset +  6, 2,
885       (iph.ip_off & IP_OFFSET)*8);
886     proto_tree_add_uint(ip_tree, hf_ip_ttl, tvb, offset +  8, 1, iph.ip_ttl);
887     proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset +  9, 1, iph.ip_p,
888         "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
889
890     ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
891     if (ipsum == 0) {
892         proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
893             "Header checksum: 0x%04x (correct)", iph.ip_sum);
894     }
895     else {
896         proto_tree_add_item_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
897         proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
898             "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph.ip_sum,
899             in_cksum_shouldbe(iph.ip_sum, ipsum));
900     }
901
902     proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, iph.ip_src);
903     proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, iph.ip_dst);
904     proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, iph.ip_src);
905     proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, iph.ip_dst);
906
907     /* Decode IP options, if any. */
908     if (hlen > sizeof (e_ip)) {
909       /* There's more than just the fixed-length header.  Decode the
910          options. */
911       optlen = hlen - sizeof (e_ip);    /* length of options, in bytes */
912       tf = proto_tree_add_text(ip_tree, tvb, offset +  20, optlen,
913         "Options: (%u bytes)", optlen);
914       field_tree = proto_item_add_subtree(tf, ett_ip_options);
915       dissect_ip_tcp_options(tvb, offset + 20, optlen,
916          ipopts, N_IP_OPTS, IPOPT_END, pinfo->fd, field_tree);
917     }
918   }
919
920   pinfo->ipproto = iph.ip_p;
921   pinfo->iplen = iph.ip_len;
922   pinfo->iphdrlen = lo_nibble(iph.ip_v_hl);
923   SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
924   SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
925   SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
926   SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
927
928   /* Skip over header + options */
929   offset += hlen;
930   nxt = iph.ip_p;
931   if (iph.ip_off & IP_OFFSET) {
932     /* fragmented */
933     if (check_col(pinfo->fd, COL_INFO))
934       col_add_fstr(pinfo->fd, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
935         ipprotostr(iph.ip_p), iph.ip_p, (iph.ip_off & IP_OFFSET) * 8);
936     dissect_data(tvb, offset, pinfo, tree);
937     return;
938   }
939
940   /*
941    * If this is the first fragment, but not the only fragment,
942    * tell the next protocol that.
943    */
944   if (iph.ip_off & IP_MF)
945     pinfo->fragmented = TRUE;
946   else
947     pinfo->fragmented = FALSE;
948
949   /* Hand off to the next protocol.
950
951      XXX - setting the columns only after trying various dissectors means
952      that if one of those dissectors throws an exception, the frame won't
953      even be labelled as an IP frame; ideally, if a frame being dissected
954      throws an exception, it'll be labelled as a mangled frame of the
955      type in question. */
956   next_tvb = tvb_new_subset(tvb, offset, -1, -1);
957   if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
958     /* Unknown protocol */
959     if (check_col(pinfo->fd, COL_INFO))
960       col_add_fstr(pinfo->fd, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
961     dissect_data(next_tvb, 0, pinfo, tree);
962   }
963 }
964
965
966 static const gchar *unreach_str[] = {"Network unreachable",
967                                      "Host unreachable",
968                                      "Protocol unreachable",
969                                      "Port unreachable",
970                                      "Fragmentation needed",
971                                      "Source route failed",
972                                      "Destination network unknown",
973                                      "Destination host unknown",
974                                      "Source host isolated",
975                                      "Network administratively prohibited",
976                                      "Host administratively prohibited",
977                                      "Network unreachable for TOS",
978                                      "Host unreachable for TOS",
979                                      "Communication administratively filtered",
980                                      "Host precedence violation",
981                                      "Precedence cutoff in effect"};
982                                      
983 #define N_UNREACH       (sizeof unreach_str / sizeof unreach_str[0])
984
985 static const gchar *redir_str[] = {"Redirect for network",
986                                    "Redirect for host",
987                                    "Redirect for TOS and network",
988                                    "Redirect for TOS and host"};
989
990 #define N_REDIRECT      (sizeof redir_str / sizeof redir_str[0])
991
992 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
993                                  "TTL equals 0 during reassembly"};
994                                  
995 #define N_TIMXCEED      (sizeof ttl_str / sizeof ttl_str[0])
996
997 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
998
999 #define N_PARAMPROB     (sizeof par_str / sizeof par_str[0])
1000
1001 static void
1002 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1003 {
1004   proto_tree *icmp_tree;
1005   proto_item *ti;
1006   guint8     icmp_type;
1007   guint8     icmp_code;
1008   guint      length, reported_length;
1009   guint16    cksum, computed_cksum;
1010   gchar      type_str[64], code_str[64] = "";
1011   guint8     num_addrs = 0;
1012   guint8     addr_entry_size = 0;
1013   int        i;
1014
1015   if (check_col(pinfo->fd, COL_PROTOCOL))
1016     col_set_str(pinfo->fd, COL_PROTOCOL, "ICMP");
1017   if (check_col(pinfo->fd, COL_INFO))
1018     col_clear(pinfo->fd, COL_INFO);
1019
1020   /* To do: check for runts, errs, etc. */
1021   icmp_type = tvb_get_guint8(tvb, 0);
1022   icmp_code = tvb_get_guint8(tvb, 1);
1023   cksum = tvb_get_ntohs(tvb, 2);
1024
1025   switch (icmp_type) {
1026     case ICMP_ECHOREPLY:
1027       strcpy(type_str, "Echo (ping) reply");
1028       break;
1029     case ICMP_UNREACH:
1030       strcpy(type_str, "Destination unreachable");
1031       if (icmp_code < N_UNREACH) {
1032         sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1033       } else {
1034         strcpy(code_str, "(Unknown - error?)");
1035       }
1036       break;
1037     case ICMP_SOURCEQUENCH:
1038       strcpy(type_str, "Source quench (flow control)");
1039       break;
1040     case ICMP_REDIRECT:
1041       strcpy(type_str, "Redirect");
1042       if (icmp_code < N_REDIRECT) {
1043         sprintf(code_str, "(%s)", redir_str[icmp_code]);
1044       } else {
1045         strcpy(code_str, "(Unknown - error?)");
1046       }
1047       break;
1048     case ICMP_ECHO:
1049       strcpy(type_str, "Echo (ping) request");
1050       break;
1051     case ICMP_RTRADVERT:
1052       strcpy(type_str, "Router advertisement");
1053       break;
1054     case ICMP_RTRSOLICIT:
1055       strcpy(type_str, "Router solicitation");
1056       break;
1057     case ICMP_TIMXCEED:
1058       strcpy(type_str, "Time-to-live exceeded");
1059       if (icmp_code < N_TIMXCEED) {
1060         sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1061       } else {
1062         strcpy(code_str, "(Unknown - error?)");
1063       }
1064       break;
1065     case ICMP_PARAMPROB:
1066       strcpy(type_str, "Parameter problem");
1067       if (icmp_code < N_PARAMPROB) {
1068         sprintf(code_str, "(%s)", par_str[icmp_code]);
1069       } else {
1070         strcpy(code_str, "(Unknown - error?)");
1071       }
1072       break;
1073     case ICMP_TSTAMP:
1074       strcpy(type_str, "Timestamp request");
1075       break;
1076     case ICMP_TSTAMPREPLY:
1077       strcpy(type_str, "Timestamp reply");
1078       break;
1079     case ICMP_IREQ:
1080       strcpy(type_str, "Information request");
1081       break;
1082     case ICMP_IREQREPLY:
1083       strcpy(type_str, "Information reply");
1084       break;
1085     case ICMP_MASKREQ:
1086       strcpy(type_str, "Address mask request");
1087       break;
1088     case ICMP_MASKREPLY:
1089       strcpy(type_str, "Address mask reply");
1090       break;
1091     default:
1092       strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1093   }
1094
1095   if (check_col(pinfo->fd, COL_INFO))
1096     col_add_str(pinfo->fd, COL_INFO, type_str);
1097
1098   if (tree) {
1099     length = tvb_length(tvb);
1100     reported_length = tvb_reported_length(tvb);
1101     ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1102     icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1103     proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1, 
1104                                icmp_type,
1105                                "Type: %u (%s)",
1106                                icmp_type, type_str);
1107     proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1, 
1108                                icmp_code,
1109                                "Code: %u %s",
1110                                icmp_code, code_str);
1111
1112     if (!pinfo->fragmented && length >= reported_length) {
1113       /* The packet isn't part of a fragmented datagram and isn't
1114          truncated, so we can checksum it. */
1115
1116       computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1117                                    reported_length);
1118       if (computed_cksum == 0) {
1119         proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1120                         cksum,
1121                         "Checksum: 0x%04x (correct)", cksum);
1122       } else {
1123         proto_tree_add_item_hidden(icmp_tree, hf_icmp_checksum_bad,
1124                         tvb, 2, 2, TRUE);
1125         proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1126                         cksum,
1127                         "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1128                         cksum, in_cksum_shouldbe(cksum, computed_cksum));
1129       }
1130     } else {
1131       proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1132     }
1133
1134     /* Decode the second 4 bytes of the packet. */
1135     switch (icmp_type) {
1136       case ICMP_ECHOREPLY:
1137       case ICMP_ECHO:
1138       case ICMP_TSTAMP:
1139       case ICMP_TSTAMPREPLY:
1140       case ICMP_IREQ:
1141       case ICMP_IREQREPLY:
1142       case ICMP_MASKREQ:
1143       case ICMP_MASKREPLY:
1144         proto_tree_add_text(icmp_tree, tvb, 4, 2, "Identifier: 0x%04x",
1145           tvb_get_ntohs(tvb, 4));
1146         proto_tree_add_text(icmp_tree, tvb, 6, 2, "Sequence number: %02x:%02x",
1147           tvb_get_guint8(tvb, 6), tvb_get_guint8(tvb, 7));
1148         break;
1149
1150        case ICMP_UNREACH:
1151          switch (icmp_code) {
1152            case ICMP_FRAG_NEEDED:
1153                  proto_tree_add_text(icmp_tree, tvb, 6, 2, "MTU of next hop: %u",
1154                    tvb_get_ntohs(tvb, 6));
1155                  break;
1156            }
1157          break;
1158
1159       case ICMP_RTRADVERT:
1160         num_addrs = tvb_get_guint8(tvb, 4);
1161         proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1162           num_addrs);
1163         addr_entry_size = tvb_get_guint8(tvb, 5);
1164         proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1165           addr_entry_size);
1166         proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1167           time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1168         break;
1169
1170       case ICMP_PARAMPROB:
1171         proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1172           tvb_get_guint8(tvb, 4));
1173         break;
1174
1175       case ICMP_REDIRECT:
1176         proto_tree_add_text(icmp_tree, tvb, 4, 4, "Gateway address: %s",
1177           ip_to_str(tvb_get_ptr(tvb, 4, 4)));
1178         break;
1179     }
1180
1181     /* Decode the additional information in the packet.  */
1182     switch (icmp_type) {
1183       case ICMP_UNREACH:
1184       case ICMP_TIMXCEED:
1185       case ICMP_PARAMPROB:
1186       case ICMP_SOURCEQUENCH:
1187       case ICMP_REDIRECT:
1188         /* Decode the IP header and first 64 bits of data from the
1189            original datagram.
1190
1191            XXX - for now, just display it as data; not all dissection
1192            routines can handle a short packet without exploding. */
1193         dissect_data(tvb, 8, pinfo, icmp_tree);
1194         break;
1195
1196       case ICMP_ECHOREPLY:
1197       case ICMP_ECHO:
1198         dissect_data(tvb, 8, pinfo, icmp_tree);
1199         break;
1200
1201       case ICMP_RTRADVERT:
1202         if (addr_entry_size == 2) {
1203           for (i = 0; i < num_addrs; i++) {
1204             proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1205               "Router address: %s",
1206               ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1207             proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1208               "Preference level: %u", tvb_get_ntohl(tvb, 12 + (i*8)));
1209           }
1210         } else
1211           dissect_data(tvb, 8, pinfo, icmp_tree);
1212         break;
1213
1214       case ICMP_TSTAMP:
1215       case ICMP_TSTAMPREPLY:
1216         proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1217           tvb_get_ntohl(tvb, 8));
1218         proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1219           tvb_get_ntohl(tvb, 12));
1220         proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1221           tvb_get_ntohl(tvb, 16));
1222         break;
1223
1224     case ICMP_MASKREQ:
1225     case ICMP_MASKREPLY:
1226         proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1227           ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1228         break;
1229     }
1230   }
1231 }
1232
1233 static void
1234 dissect_igmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1235 {
1236   e_igmp     ih;
1237   proto_tree *igmp_tree;
1238   proto_item *ti;
1239   gchar      *type_str;
1240
1241   if (check_col(pinfo->fd, COL_PROTOCOL))
1242     col_set_str(pinfo->fd, COL_PROTOCOL, "IGMP");
1243   if (check_col(pinfo->fd, COL_INFO))
1244     col_clear(pinfo->fd, COL_INFO);
1245
1246   /* Avoids alignment problems on many architectures. */
1247   memcpy(&ih, tvb_get_ptr(tvb, 0, sizeof(e_igmp)), sizeof(e_igmp));
1248   
1249   switch (lo_nibble(ih.igmp_v_t)) {
1250     case IGMP_M_QRY:
1251       type_str = "Router query";
1252       break;
1253     case IGMP_V1_M_RPT:
1254       type_str = "Host response (v1)";
1255       break;
1256     case IGMP_V2_LV_GRP:
1257       type_str = "Leave group (v2)";
1258       break;
1259     case IGMP_DVMRP:
1260       type_str = "DVMRP";
1261       break;
1262     case IGMP_PIM:
1263       type_str = "PIM";
1264       break;
1265     case IGMP_V2_M_RPT:
1266       type_str = "Host response (v2)";
1267       break;
1268     case IGMP_MTRC_RESP:
1269       type_str = "Traceroute response";
1270       break;
1271     case IGMP_MTRC:
1272       type_str = "Traceroute message";
1273       break;
1274     default:
1275       type_str = "Unknown IGMP";
1276   }
1277
1278   if (check_col(pinfo->fd, COL_INFO))
1279     col_add_str(pinfo->fd, COL_INFO, type_str);
1280   if (tree) {
1281     ti = proto_tree_add_item(tree, proto_igmp, tvb, 0, 8, FALSE);
1282     igmp_tree = proto_item_add_subtree(ti, ett_igmp);
1283     proto_tree_add_uint(igmp_tree, hf_igmp_version, tvb, 0,     1, 
1284                         hi_nibble(ih.igmp_v_t));
1285     proto_tree_add_uint_format(igmp_tree, hf_igmp_type, tvb,  0    , 1, 
1286                                lo_nibble(ih.igmp_v_t),
1287                                "Type: %u (%s)",
1288                                lo_nibble(ih.igmp_v_t), type_str);
1289     proto_tree_add_item(igmp_tree, hf_igmp_unused, tvb,  1, 1, FALSE);
1290     proto_tree_add_item(igmp_tree, hf_igmp_checksum, tvb,  2, 2, FALSE);
1291     proto_tree_add_ipv4(igmp_tree, hf_igmp_group, tvb,  4, 4, ih.igmp_gaddr);
1292   }
1293 }
1294
1295 void
1296 proto_register_igmp(void)
1297 {
1298         static hf_register_info hf[] = {
1299
1300                 { &hf_igmp_version,
1301                 { "Version",            "igmp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1302                         "" }},
1303
1304                 { &hf_igmp_type,
1305                 { "Type",               "igmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1306                         "" }},
1307
1308                 { &hf_igmp_unused,
1309                 { "Unused",             "igmp.unused", FT_UINT8, BASE_HEX, NULL, 0x0,
1310                         "" }},
1311
1312                 { &hf_igmp_checksum,
1313                 { "Checksum",           "igmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1314                         "" }},
1315
1316                 { &hf_igmp_group,
1317                 { "Group address",      "igmp.group", FT_IPv4, BASE_NONE, NULL, 0x0,
1318                         "" }},
1319         };
1320         static gint *ett[] = {
1321                 &ett_igmp,
1322         };
1323
1324         proto_igmp = proto_register_protocol("Internet Group Management Protocol",
1325             "IGMP", "igmp");
1326         proto_register_field_array(proto_igmp, hf, array_length(hf));
1327         proto_register_subtree_array(ett, array_length(ett));
1328 }
1329
1330 void
1331 proto_reg_handoff_igmp(void)
1332 {
1333         dissector_add("ip.proto", IP_PROTO_IGMP, dissect_igmp, proto_igmp);
1334 }
1335
1336 void
1337 proto_register_ip(void)
1338 {
1339         static hf_register_info hf[] = {
1340
1341                 { &hf_ip_version,
1342                 { "Version",            "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1343                         "" }},
1344
1345                 { &hf_ip_hdr_len,
1346                 { "Header Length",      "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1347                         "" }},
1348
1349                 { &hf_ip_dsfield,
1350                 { "Differentiated Services field",      "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1351                         "" }},
1352
1353                 { &hf_ip_dsfield_dscp,
1354                 { "Differentiated Services Codepoint",  "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1355                         VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1356                         "" }},
1357
1358                 { &hf_ip_dsfield_ect,
1359                 { "ECN-Capable Transport (ECT)",        "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1360                         IPDSFIELD_ECT_MASK,
1361                         "" }},
1362
1363                 { &hf_ip_dsfield_ce,
1364                 { "ECN-CE",     "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1365                         IPDSFIELD_CE_MASK,
1366                         "" }},
1367
1368                 { &hf_ip_tos,
1369                 { "Type of Service",    "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1370                         "" }},
1371
1372                 { &hf_ip_tos_precedence,
1373                 { "Precedence",         "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1374                         IPTOS_PREC_MASK,
1375                         "" }},
1376
1377                 { &hf_ip_tos_delay,
1378                 { "Delay",              "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1379                         IPTOS_LOWDELAY,
1380                         "" }},
1381
1382                 { &hf_ip_tos_throughput,
1383                 { "Throughput",         "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1384                         IPTOS_THROUGHPUT,
1385                         "" }},
1386
1387                 { &hf_ip_tos_reliability,
1388                 { "Reliability",        "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1389                         IPTOS_RELIABILITY,
1390                         "" }},
1391
1392                 { &hf_ip_tos_cost,
1393                 { "Cost",               "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1394                         IPTOS_LOWCOST,
1395                         "" }},
1396
1397                 { &hf_ip_len,
1398                 { "Total Length",       "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1399                         "" }},
1400
1401                 { &hf_ip_id,
1402                 { "Identification",     "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1403                         "" }},
1404
1405                 { &hf_ip_dst,
1406                 { "Destination",        "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1407                         "" }},
1408
1409                 { &hf_ip_src,
1410                 { "Source",             "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1411                         "" }},
1412
1413                 { &hf_ip_addr,
1414                 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1415                         "" }},
1416
1417                 { &hf_ip_flags,
1418                 { "Flags",              "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1419                         "" }},
1420
1421                 { &hf_ip_flags_df,
1422                 { "Don't fragment",     "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1423                         "" }},
1424
1425                 { &hf_ip_flags_mf,
1426                 { "More fragments",     "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1427                         "" }},
1428
1429                 { &hf_ip_frag_offset,
1430                 { "Fragment offset",    "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1431                         "" }},
1432
1433                 { &hf_ip_ttl,
1434                 { "Time to live",       "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1435                         "" }},
1436
1437                 { &hf_ip_proto,
1438                 { "Protocol",           "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1439                         "" }},
1440
1441                 { &hf_ip_checksum,
1442                 { "Header checksum",    "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1443                         "" }},
1444
1445                 { &hf_ip_checksum_bad,
1446                 { "Bad Header checksum",        "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1447                         "" }},
1448         };
1449         static gint *ett[] = {
1450                 &ett_ip,
1451                 &ett_ip_dsfield,
1452                 &ett_ip_tos,
1453                 &ett_ip_off,
1454                 &ett_ip_options,
1455                 &ett_ip_option_sec,
1456                 &ett_ip_option_route,
1457                 &ett_ip_option_timestamp,
1458         };
1459         module_t *ip_module;
1460
1461         proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1462         proto_register_field_array(proto_ip, hf, array_length(hf));
1463         proto_register_subtree_array(ett, array_length(ett));
1464
1465         /* subdissector code */
1466         ip_dissector_table = register_dissector_table("ip.proto");
1467
1468         /* Register a configuration option for decoding TOS as DSCP */
1469         ip_module = prefs_register_protocol(proto_ip, NULL);
1470         prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1471             "Decode IPv4 TOS field as DiffServ field",
1472 "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1473             &g_ip_dscp_actif);
1474
1475         register_dissector("ip", dissect_ip, proto_ip);
1476 }
1477
1478 void
1479 proto_reg_handoff_ip(void)
1480 {
1481         dissector_add("ethertype", ETHERTYPE_IP, dissect_ip, proto_ip);
1482         dissector_add("ppp.protocol", PPP_IP, dissect_ip, proto_ip);
1483         dissector_add("ppp.protocol", ETHERTYPE_IP, dissect_ip, proto_ip);
1484         dissector_add("gre.proto", ETHERTYPE_IP, dissect_ip, proto_ip);
1485         dissector_add("gre.proto", GRE_WCCP, dissect_ip, proto_ip);
1486         dissector_add("llc.dsap", SAP_IP, dissect_ip, proto_ip);
1487         dissector_add("ip.proto", IP_PROTO_IPIP, dissect_ip, proto_ip);
1488         dissector_add("null.type", BSD_AF_INET, dissect_ip, proto_ip);
1489         dissector_add("chdlctype", ETHERTYPE_IP, dissect_ip, proto_ip);
1490         dissector_add("fr.ietf", NLPID_IP, dissect_ip, proto_ip);
1491 }
1492
1493 void
1494 proto_register_icmp(void)
1495 {
1496   static hf_register_info hf[] = {
1497     
1498     { &hf_icmp_type,
1499       { "Type",         "icmp.type",            FT_UINT8, BASE_DEC,     NULL, 0x0,
1500         "" }},
1501
1502     { &hf_icmp_code,
1503       { "Code",         "icmp.code",            FT_UINT8, BASE_HEX,     NULL, 0x0,
1504         "" }},    
1505
1506     { &hf_icmp_checksum,
1507       { "Checksum",     "icmp.checksum",        FT_UINT16, BASE_HEX,    NULL, 0x0,
1508         "" }},
1509
1510     { &hf_icmp_checksum_bad,
1511       { "Bad Checksum", "icmp.checksum_bad",    FT_BOOLEAN, BASE_NONE,  NULL, 0x0,
1512         "" }},
1513   };
1514   static gint *ett[] = {
1515     &ett_icmp,
1516   };
1517   
1518   proto_icmp = proto_register_protocol("Internet Control Message Protocol", 
1519                                        "ICMP", "icmp");
1520   proto_register_field_array(proto_icmp, hf, array_length(hf));
1521   proto_register_subtree_array(ett, array_length(ett));
1522 }
1523
1524 void
1525 proto_reg_handoff_icmp(void)
1526 {
1527   dissector_add("ip.proto", IP_PROTO_ICMP, dissect_icmp, proto_icmp);
1528 }