Small fix for dissect_ndr_nt_UNICODE_STRING_str() in packet-dcerpc-nt.c
[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.163 2002/02/27 05:45:48 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  * 
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32
33 #ifdef HAVE_NETINET_IN_H
34 # include <netinet/in.h>
35 #endif
36
37 #include <stdio.h>
38 #include <string.h>
39 #include <glib.h>
40
41 #ifdef NEED_SNPRINTF_H
42 # include "snprintf.h"
43 #endif
44
45 #include <epan/packet.h>
46 #include <epan/resolv.h>
47 #include "ipproto.h"
48 #include "prefs.h"
49 #include "reassemble.h"
50 #include "etypes.h"
51 #include "greproto.h"
52 #include "ppptypes.h"
53 #include "llcsaps.h"
54 #include "aftypes.h"
55 #include "packet-ip.h"
56 #include "packet-ipsec.h"
57 #include "in_cksum.h"
58 #include "nlpid.h"
59
60 static void dissect_icmp(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 /* Defragment fragmented IP datagrams */
66 static gboolean ip_defragment = FALSE;
67
68 /* Place IP summary in proto tree */
69 static gboolean ip_summary_in_tree = TRUE;
70
71 static int proto_ip = -1;
72 static int hf_ip_version = -1;
73 static int hf_ip_hdr_len = -1;
74 static int hf_ip_dsfield = -1;
75 static int hf_ip_dsfield_dscp = -1;
76 static int hf_ip_dsfield_ect = -1;
77 static int hf_ip_dsfield_ce = -1;
78 static int hf_ip_tos = -1;
79 static int hf_ip_tos_precedence = -1;
80 static int hf_ip_tos_delay = -1;
81 static int hf_ip_tos_throughput = -1;
82 static int hf_ip_tos_reliability = -1;
83 static int hf_ip_tos_cost = -1;
84 static int hf_ip_len = -1;
85 static int hf_ip_id = -1;
86 static int hf_ip_dst = -1;
87 static int hf_ip_src = -1;
88 static int hf_ip_addr = -1;
89 static int hf_ip_flags = -1;
90 static int hf_ip_flags_df = -1;
91 static int hf_ip_flags_mf = -1;
92 static int hf_ip_frag_offset = -1;
93 static int hf_ip_ttl = -1;
94 static int hf_ip_proto = -1;
95 static int hf_ip_checksum = -1;
96 static int hf_ip_checksum_bad = -1;
97 static int hf_ip_fragments = -1;
98 static int hf_ip_fragment = -1;
99 static int hf_ip_fragment_overlap = -1;
100 static int hf_ip_fragment_overlap_conflict = -1;
101 static int hf_ip_fragment_multiple_tails = -1;
102 static int hf_ip_fragment_too_long_fragment = -1;
103 static int hf_ip_fragment_error = -1;
104
105 static gint ett_ip = -1;
106 static gint ett_ip_dsfield = -1;
107 static gint ett_ip_tos = -1;
108 static gint ett_ip_off = -1;
109 static gint ett_ip_options = -1;
110 static gint ett_ip_option_sec = -1;
111 static gint ett_ip_option_route = -1;
112 static gint ett_ip_option_timestamp = -1;
113 static gint ett_ip_fragments = -1;
114 static gint ett_ip_fragment  = -1;
115
116 /* Used by IPv6 as well, so not static */
117 dissector_table_t ip_dissector_table;
118
119 static dissector_handle_t ip_handle;
120 static dissector_handle_t data_handle;
121
122 static int proto_icmp = -1;
123 static int hf_icmp_type = -1;
124 static int hf_icmp_code = -1;
125 static int hf_icmp_checksum = -1;
126 static int hf_icmp_checksum_bad = -1;
127
128 /* Mobile ip */
129 static int hf_icmp_mip_type = -1;
130 static int hf_icmp_mip_length = -1;
131 static int hf_icmp_mip_prefix_length = -1;
132 static int hf_icmp_mip_seq = -1;
133 static int hf_icmp_mip_life = -1;
134 static int hf_icmp_mip_flags = -1;
135 static int hf_icmp_mip_r = -1;
136 static int hf_icmp_mip_b = -1;
137 static int hf_icmp_mip_h = -1;
138 static int hf_icmp_mip_f = -1;
139 static int hf_icmp_mip_m = -1;
140 static int hf_icmp_mip_g = -1;
141 static int hf_icmp_mip_v = -1;
142 static int hf_icmp_mip_res = -1;
143 static int hf_icmp_mip_reserved = -1;
144 static int hf_icmp_mip_coa = -1;
145 static int hf_icmp_mip_challenge = -1;
146
147 static gint ett_icmp = -1;
148 static gint ett_icmp_mip = -1;
149 static gint ett_icmp_mip_flags = -1;
150
151 /* ICMP definitions */
152
153 #define ICMP_ECHOREPLY     0
154 #define ICMP_UNREACH       3
155 #define ICMP_SOURCEQUENCH  4
156 #define ICMP_REDIRECT      5
157 #define ICMP_ECHO          8
158 #define ICMP_RTRADVERT     9
159 #define ICMP_RTRSOLICIT   10
160 #define ICMP_TIMXCEED     11
161 #define ICMP_PARAMPROB    12
162 #define ICMP_TSTAMP       13
163 #define ICMP_TSTAMPREPLY  14
164 #define ICMP_IREQ         15
165 #define ICMP_IREQREPLY    16
166 #define ICMP_MASKREQ      17
167 #define ICMP_MASKREPLY    18
168
169 /* ICMP UNREACHABLE */
170
171 #define ICMP_NET_UNREACH        0       /* Network Unreachable */
172 #define ICMP_HOST_UNREACH       1       /* Host Unreachable */
173 #define ICMP_PROT_UNREACH       2       /* Protocol Unreachable */
174 #define ICMP_PORT_UNREACH       3       /* Port Unreachable */
175 #define ICMP_FRAG_NEEDED        4       /* Fragmentation Needed/DF set */
176 #define ICMP_SR_FAILED          5       /* Source Route failed */
177 #define ICMP_NET_UNKNOWN        6
178 #define ICMP_HOST_UNKNOWN       7
179 #define ICMP_HOST_ISOLATED      8
180 #define ICMP_NET_ANO            9
181 #define ICMP_HOST_ANO           10
182 #define ICMP_NET_UNR_TOS        11
183 #define ICMP_HOST_UNR_TOS       12
184 #define ICMP_PKT_FILTERED       13      /* Packet filtered */
185 #define ICMP_PREC_VIOLATION     14      /* Precedence violation */
186 #define ICMP_PREC_CUTOFF        15      /* Precedence cut off */
187
188
189 /* IP structs and definitions */
190
191 typedef struct _e_ip 
192    {
193    guint8  ip_v_hl; /* combines ip_v and ip_hl */
194    guint8  ip_tos;
195    guint16 ip_len;
196    guint16 ip_id;
197    guint16 ip_off;
198    guint8  ip_ttl;
199    guint8  ip_p;
200    guint16 ip_sum;
201    guint32 ip_src;
202    guint32 ip_dst;
203    } e_ip;
204
205 /* Offsets of fields within an IP header. */
206 #define IPH_V_HL        0
207 #define IPH_TOS         1
208 #define IPH_LEN         2
209 #define IPH_ID          4
210 #define IPH_TTL         6
211 #define IPH_OFF         8
212 #define IPH_P           9
213 #define IPH_SUM         10
214 #define IPH_SRC         12
215 #define IPH_DST         16
216
217 /* Minimum IP header length. */
218 #define IPH_MIN_LEN     20
219
220 /* IP flags. */
221 #define IP_CE           0x8000          /* Flag: "Congestion"           */
222 #define IP_DF           0x4000          /* Flag: "Don't Fragment"       */
223 #define IP_MF           0x2000          /* Flag: "More Fragments"       */
224 #define IP_OFFSET       0x1FFF          /* "Fragment Offset" part       */
225
226 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
227 #define IPDSFIELD_DSCP_MASK     0xFC
228 #define IPDSFIELD_ECN_MASK     0x03
229 #define IPDSFIELD_DSCP_SHIFT    2
230 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
231 #define IPDSFIELD_ECN(dsfield)  ((dsfield)&IPDSFIELD_ECN_MASK)
232 #define IPDSFIELD_DSCP_DEFAULT  0x00
233 #define IPDSFIELD_DSCP_CS1      0x08
234 #define IPDSFIELD_DSCP_CS2      0x10
235 #define IPDSFIELD_DSCP_CS3      0x18
236 #define IPDSFIELD_DSCP_CS4      0x20
237 #define IPDSFIELD_DSCP_CS5      0x28
238 #define IPDSFIELD_DSCP_CS6      0x30
239 #define IPDSFIELD_DSCP_CS7      0x38
240 #define IPDSFIELD_DSCP_AF11     0x0A
241 #define IPDSFIELD_DSCP_AF12     0x0C
242 #define IPDSFIELD_DSCP_AF13     0x0E
243 #define IPDSFIELD_DSCP_AF21     0x12
244 #define IPDSFIELD_DSCP_AF22     0x14
245 #define IPDSFIELD_DSCP_AF23     0x16
246 #define IPDSFIELD_DSCP_AF31     0x1A
247 #define IPDSFIELD_DSCP_AF32     0x1C
248 #define IPDSFIELD_DSCP_AF33     0x1E
249 #define IPDSFIELD_DSCP_AF41     0x22
250 #define IPDSFIELD_DSCP_AF42     0x24
251 #define IPDSFIELD_DSCP_AF43     0x26
252 #define IPDSFIELD_DSCP_EF       0x2E
253 #define IPDSFIELD_ECT_MASK      0x02
254 #define IPDSFIELD_CE_MASK       0x01
255
256 /* IP TOS, superseded by the DS Field, RFC 2474. */
257 #define IPTOS_TOS_MASK    0x1E
258 #define IPTOS_TOS(tos)    ((tos) & IPTOS_TOS_MASK)
259 #define IPTOS_NONE        0x00
260 #define IPTOS_LOWCOST     0x02
261 #define IPTOS_RELIABILITY 0x04
262 #define IPTOS_THROUGHPUT  0x08
263 #define IPTOS_LOWDELAY    0x10
264 #define IPTOS_SECURITY    0x1E
265
266 #define IPTOS_PREC_MASK         0xE0
267 #define IPTOS_PREC_SHIFT        5
268 #define IPTOS_PREC(tos)         (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
269 #define IPTOS_PREC_NETCONTROL           7
270 #define IPTOS_PREC_INTERNETCONTROL      6
271 #define IPTOS_PREC_CRITIC_ECP           5
272 #define IPTOS_PREC_FLASHOVERRIDE        4
273 #define IPTOS_PREC_FLASH                3
274 #define IPTOS_PREC_IMMEDIATE            2
275 #define IPTOS_PREC_PRIORITY             1
276 #define IPTOS_PREC_ROUTINE              0
277
278 /* IP options */
279 #define IPOPT_COPY              0x80
280
281 #define IPOPT_CONTROL           0x00
282 #define IPOPT_RESERVED1         0x20
283 #define IPOPT_MEASUREMENT       0x40
284 #define IPOPT_RESERVED2         0x60
285
286 #define IPOPT_END       (0 |IPOPT_CONTROL)
287 #define IPOPT_NOOP      (1 |IPOPT_CONTROL)
288 #define IPOPT_SEC       (2 |IPOPT_CONTROL|IPOPT_COPY)
289 #define IPOPT_LSRR      (3 |IPOPT_CONTROL|IPOPT_COPY)
290 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
291 #define IPOPT_RR        (7 |IPOPT_CONTROL)
292 #define IPOPT_SID       (8 |IPOPT_CONTROL|IPOPT_COPY)
293 #define IPOPT_SSRR      (9 |IPOPT_CONTROL|IPOPT_COPY)
294 #define IPOPT_RA        (20|IPOPT_CONTROL|IPOPT_COPY)
295
296 /* IP option lengths */
297 #define IPOLEN_SEC      11
298 #define IPOLEN_LSRR_MIN 3
299 #define IPOLEN_TIMESTAMP_MIN 5
300 #define IPOLEN_RR_MIN   3
301 #define IPOLEN_SID      4
302 #define IPOLEN_SSRR_MIN 3
303 #define IPOLEN_RA       4
304
305 #define IPSEC_UNCLASSIFIED      0x0000
306 #define IPSEC_CONFIDENTIAL      0xF135
307 #define IPSEC_EFTO              0x789A
308 #define IPSEC_MMMM              0xBC4D
309 #define IPSEC_RESTRICTED        0xAF13
310 #define IPSEC_SECRET            0xD788
311 #define IPSEC_TOPSECRET         0x6BC5
312 #define IPSEC_RESERVED1         0x35E2
313 #define IPSEC_RESERVED2         0x9AF1
314 #define IPSEC_RESERVED3         0x4D78
315 #define IPSEC_RESERVED4         0x24BD
316 #define IPSEC_RESERVED5         0x135E
317 #define IPSEC_RESERVED6         0x89AF
318 #define IPSEC_RESERVED7         0xC4D6
319 #define IPSEC_RESERVED8         0xE26B
320
321 #define IPOPT_TS_TSONLY         0               /* timestamps only */
322 #define IPOPT_TS_TSANDADDR      1               /* timestamps and addresses */
323 #define IPOPT_TS_PRESPEC        3               /* specified modules only */
324
325 /*
326  * defragmentation of IPv4
327  */
328 static GHashTable *ip_fragment_table = NULL;
329
330 static void
331 ip_defragment_init(void)
332 {
333   fragment_table_init(&ip_fragment_table);
334 }
335
336 void
337 capture_ip(const u_char *pd, int offset, int len, packet_counts *ld) {
338   if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
339     ld->other++;
340     return;
341   }
342   switch (pd[offset + 9]) {
343     case IP_PROTO_SCTP:
344       ld->sctp++;
345       break;
346     case IP_PROTO_TCP:
347       ld->tcp++;
348       break;
349     case IP_PROTO_UDP:
350       ld->udp++;
351       break;
352     case IP_PROTO_ICMP:
353       ld->icmp++;
354       break;
355     case IP_PROTO_OSPF:
356       ld->ospf++;
357       break;
358     case IP_PROTO_GRE:
359       ld->gre++;
360       break;
361     case IP_PROTO_VINES:
362       ld->vines++;
363       break;
364     default:
365       ld->other++;
366   }
367 }
368
369 static void
370 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
371                         guint optlen, packet_info *pinfo, proto_tree *opt_tree)
372 {
373   proto_tree *field_tree = NULL;
374   proto_item *tf;
375   guint      val;
376   static const value_string secl_vals[] = {
377     {IPSEC_UNCLASSIFIED, "Unclassified"},
378     {IPSEC_CONFIDENTIAL, "Confidential"},
379     {IPSEC_EFTO,         "EFTO"        },
380     {IPSEC_MMMM,         "MMMM"        },
381     {IPSEC_RESTRICTED,   "Restricted"  },
382     {IPSEC_SECRET,       "Secret"      },
383     {IPSEC_TOPSECRET,    "Top secret"  },
384     {IPSEC_RESERVED1,    "Reserved"    },
385     {IPSEC_RESERVED2,    "Reserved"    },
386     {IPSEC_RESERVED3,    "Reserved"    },
387     {IPSEC_RESERVED4,    "Reserved"    },
388     {IPSEC_RESERVED5,    "Reserved"    },
389     {IPSEC_RESERVED6,    "Reserved"    },
390     {IPSEC_RESERVED7,    "Reserved"    },
391     {IPSEC_RESERVED8,    "Reserved"    },
392     {0,                  NULL          } };
393
394   tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s:", optp->name);
395   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
396   offset += 2;
397
398   val = tvb_get_ntohs(tvb, offset);
399   proto_tree_add_text(field_tree, tvb, offset,       2,
400               "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
401   offset += 2;
402
403   val = tvb_get_ntohs(tvb, offset);
404   proto_tree_add_text(field_tree, tvb, offset,         2,
405               "Compartments: %u", val);
406   offset += 2;
407
408   proto_tree_add_text(field_tree, tvb, offset,         2,
409               "Handling restrictions: %c%c",
410               tvb_get_guint8(tvb, offset),
411               tvb_get_guint8(tvb, offset + 1));
412   offset += 2;
413
414   proto_tree_add_text(field_tree, tvb, offset,         3,
415               "Transmission control code: %c%c%c",
416               tvb_get_guint8(tvb, offset),
417               tvb_get_guint8(tvb, offset + 1),
418               tvb_get_guint8(tvb, offset + 2));
419 }
420
421 static void
422 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
423                         guint optlen, packet_info *pinfo, proto_tree *opt_tree)
424 {
425   proto_tree *field_tree = NULL;
426   proto_item *tf;
427   int ptr;
428   int optoffset = 0;
429   struct in_addr addr;
430
431   tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s (%u bytes)",
432                                 optp->name, optlen);
433   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
434
435   optoffset += 2;       /* skip past type and length */
436   optlen -= 2;          /* subtract size of type and length */
437
438   ptr = tvb_get_guint8(tvb, offset + optoffset);
439   proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
440               "Pointer: %d%s", ptr,
441               ((ptr < 4) ? " (points before first address)" :
442                ((ptr & 3) ? " (points to middle of address)" : "")));
443   optoffset++;
444   optlen--;
445   ptr--;        /* ptr is 1-origin */
446
447   while (optlen > 0) {
448     if (optlen < 4) {
449       proto_tree_add_text(field_tree, tvb, offset,      optlen,
450         "(suboption would go past end of option)");
451       break;
452     }
453
454     /* Avoids alignment problems on many architectures. */
455     tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
456
457     proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
458               "%s%s",
459               ((addr.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_addr)),
460               ((optoffset == ptr) ? " <- (current)" : ""));
461     optoffset += 4;
462     optlen -= 4;
463   }
464 }
465
466 static void
467 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
468                         guint optlen, packet_info *pinfo, proto_tree *opt_tree)
469 {
470   proto_tree_add_text(opt_tree, tvb, offset,      optlen,
471     "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
472   return;
473 }
474
475 static void
476 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
477     int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
478 {
479   proto_tree *field_tree = NULL;
480   proto_item *tf;
481   int        ptr;
482   int        optoffset = 0;
483   int        flg;
484   static const value_string flag_vals[] = {
485     {IPOPT_TS_TSONLY,    "Time stamps only"                      },
486     {IPOPT_TS_TSANDADDR, "Time stamp and address"                },
487     {IPOPT_TS_PRESPEC,   "Time stamps for prespecified addresses"},
488     {0,                  NULL                                    } };
489   struct in_addr addr;
490   guint ts;
491
492   tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s:", optp->name);
493   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
494
495   optoffset += 2;       /* skip past type and length */
496   optlen -= 2;          /* subtract size of type and length */
497
498   ptr = tvb_get_guint8(tvb, offset + optoffset);
499   proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
500               "Pointer: %d%s", ptr,
501               ((ptr < 5) ? " (points before first address)" :
502                (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
503   optoffset++;
504   optlen--;
505   ptr--;        /* ptr is 1-origin */
506
507   flg = tvb_get_guint8(tvb, offset + optoffset);
508   proto_tree_add_text(field_tree, tvb, offset + optoffset,   1,
509         "Overflow: %u", flg >> 4);
510   flg &= 0xF;
511   proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
512         "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
513   optoffset++;
514   optlen--;
515
516   while (optlen > 0) {
517     if (flg == IPOPT_TS_TSANDADDR) {
518       if (optlen < 8) {
519         proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
520           "(suboption would go past end of option)");
521         break;
522       }
523       tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
524       ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
525       optlen -= 8;
526       proto_tree_add_text(field_tree, tvb, offset + optoffset,      8,
527           "Address = %s, time stamp = %u",
528           ((addr.s_addr == 0) ? "-" :  (char *)get_hostname(addr.s_addr)),
529           ts);
530       optoffset += 8;
531     } else {
532       if (optlen < 4) {
533         proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
534           "(suboption would go past end of option)");
535         break;
536       }
537       ts = tvb_get_ntohl(tvb, offset + optoffset);
538       optlen -= 4;
539       proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
540           "Time stamp = %u", ts);
541       optoffset += 4;
542     }
543   }
544 }
545
546 static void
547 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
548                 guint optlen, packet_info *pinfo, proto_tree *opt_tree)
549 {
550   /* Router-Alert, as defined by RFC2113 */
551   int opt = tvb_get_ntohs(tvb, offset + 2);
552   static const value_string ra_opts[] = { 
553         {0, "Every router examines packet"},
554         {0, NULL}
555   };
556   
557   proto_tree_add_text(opt_tree, tvb, offset,      optlen,
558     "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
559   return;
560 }
561
562 static const ip_tcp_opt ipopts[] = {
563   {
564     IPOPT_END,
565     "EOL",
566     NULL,
567     NO_LENGTH,
568     0,
569     NULL,
570   },
571   {
572     IPOPT_NOOP,
573     "NOP",
574     NULL,
575     NO_LENGTH,
576     0,
577     NULL,
578   },
579   {
580     IPOPT_SEC,
581     "Security",
582     &ett_ip_option_sec,
583     FIXED_LENGTH,
584     IPOLEN_SEC,
585     dissect_ipopt_security
586   },
587   {
588     IPOPT_SSRR,
589     "Strict source route",
590     &ett_ip_option_route,
591     VARIABLE_LENGTH,
592     IPOLEN_SSRR_MIN,
593     dissect_ipopt_route
594   },
595   {
596     IPOPT_LSRR,
597     "Loose source route",
598     &ett_ip_option_route,
599     VARIABLE_LENGTH,
600     IPOLEN_LSRR_MIN,
601     dissect_ipopt_route
602   },
603   {
604     IPOPT_RR,
605     "Record route",
606     &ett_ip_option_route,
607     VARIABLE_LENGTH,
608     IPOLEN_RR_MIN,
609     dissect_ipopt_route
610   },
611   {
612     IPOPT_SID,
613     "Stream identifier",
614     NULL,
615     FIXED_LENGTH,
616     IPOLEN_SID,
617     dissect_ipopt_sid
618   },
619   {
620     IPOPT_TIMESTAMP,
621     "Time stamp",
622     &ett_ip_option_timestamp,
623     VARIABLE_LENGTH,
624     IPOLEN_TIMESTAMP_MIN,
625     dissect_ipopt_timestamp
626   },
627   {
628     IPOPT_RA,
629     "Router Alert",
630     NULL,
631     FIXED_LENGTH,
632     IPOLEN_RA,
633     dissect_ipopt_ra
634   },
635 };
636
637 #define N_IP_OPTS       (sizeof ipopts / sizeof ipopts[0])
638
639 /* Dissect the IP or TCP options in a packet. */
640 void
641 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
642                         const ip_tcp_opt *opttab, int nopts, int eol,
643                         packet_info *pinfo, proto_tree *opt_tree)
644 {
645   u_char            opt;
646   const ip_tcp_opt *optp;
647   opt_len_type      len_type;
648   unsigned int      optlen;
649   char             *name;
650   char              name_str[7+1+1+2+2+1+1];    /* "Unknown (0x%02x)" */
651   void            (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
652                                 int, guint, packet_info *, proto_tree *);
653   guint             len;
654
655   while (length > 0) {
656     opt = tvb_get_guint8(tvb, offset);
657     for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
658       if (optp->optcode == opt)
659         break;
660     }
661     if (optp == &opttab[nopts]) {
662       /* We assume that the only NO_LENGTH options are EOL and NOP options,
663          so that we can treat unknown options as VARIABLE_LENGTH with a
664          minimum of 2, and at least be able to move on to the next option
665          by using the length in the option. */
666       optp = NULL;      /* indicate that we don't know this option */
667       len_type = VARIABLE_LENGTH;
668       optlen = 2;
669       snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
670       name = name_str;
671       dissect = NULL;
672     } else {
673       len_type = optp->len_type;
674       optlen = optp->optlen;
675       name = optp->name;
676       dissect = optp->dissect;
677     }
678     --length;      /* account for type byte */
679     if (len_type != NO_LENGTH) {
680       /* Option has a length. Is it in the packet? */
681       if (length == 0) {
682         /* Bogus - packet must at least include option code byte and
683            length byte! */
684         proto_tree_add_text(opt_tree, tvb, offset,      1,
685               "%s (length byte past end of options)", name);
686         return;
687       }
688       len = tvb_get_guint8(tvb, offset + 1);  /* total including type, len */
689       --length;    /* account for length byte */
690       if (len < 2) {
691         /* Bogus - option length is too short to include option code and
692            option length. */
693         proto_tree_add_text(opt_tree, tvb, offset,      2,
694               "%s (with too-short option length = %u byte%s)", name,
695               len, plurality(len, "", "s"));
696         return;
697       } else if (len - 2 > length) {
698         /* Bogus - option goes past the end of the header. */
699         proto_tree_add_text(opt_tree, tvb, offset,      length,
700               "%s (option length = %u byte%s says option goes past end of options)",
701               name, len, plurality(len, "", "s"));
702         return;
703       } else if (len_type == FIXED_LENGTH && len != optlen) {
704         /* Bogus - option length isn't what it's supposed to be for this
705            option. */
706         proto_tree_add_text(opt_tree, tvb, offset,      len,
707               "%s (with option length = %u byte%s; should be %u)", name,
708               len, plurality(len, "", "s"), optlen);
709         return;
710       } else if (len_type == VARIABLE_LENGTH && len < optlen) {
711         /* Bogus - option length is less than what it's supposed to be for
712            this option. */
713         proto_tree_add_text(opt_tree, tvb, offset,      len,
714               "%s (with option length = %u byte%s; should be >= %u)", name,
715               len, plurality(len, "", "s"), optlen);
716         return;
717       } else {
718         if (optp == NULL) {
719           proto_tree_add_text(opt_tree, tvb, offset,    len, "%s (%u byte%s)",
720                                 name, len, plurality(len, "", "s"));
721         } else {
722           if (dissect != NULL) {
723             /* Option has a dissector. */
724             (*dissect)(optp, tvb, offset,          len, pinfo, opt_tree);
725           } else {
726             /* Option has no data, hence no dissector. */
727             proto_tree_add_text(opt_tree, tvb, offset,  len, "%s", name);
728           }
729         }
730         len -= 2;       /* subtract size of type and length */
731         offset += 2 + len;
732       }
733       length -= len;
734     } else {
735       proto_tree_add_text(opt_tree, tvb, offset,      1, "%s", name);
736       offset += 1;
737     }
738     if (opt == eol)
739       break;
740   }
741 }
742
743 const value_string dscp_vals[] = {
744                   { IPDSFIELD_DSCP_DEFAULT, "Default"               },
745                   { IPDSFIELD_DSCP_CS1,     "Class Selector 1"      },
746                   { IPDSFIELD_DSCP_CS2,     "Class Selector 2"      },
747                   { IPDSFIELD_DSCP_CS3,     "Class Selector 3"      },
748                   { IPDSFIELD_DSCP_CS4,     "Class Selector 4"      },
749                   { IPDSFIELD_DSCP_CS5,     "Class Selector 5"      },
750                   { IPDSFIELD_DSCP_CS6,     "Class Selector 6"      },
751                   { IPDSFIELD_DSCP_CS7,     "Class Selector 7"      },
752                   { IPDSFIELD_DSCP_AF11,    "Assured Forwarding 11" },
753                   { IPDSFIELD_DSCP_AF12,    "Assured Forwarding 12" },
754                   { IPDSFIELD_DSCP_AF13,    "Assured Forwarding 13" },
755                   { IPDSFIELD_DSCP_AF21,    "Assured Forwarding 21" },
756                   { IPDSFIELD_DSCP_AF22,    "Assured Forwarding 22" },
757                   { IPDSFIELD_DSCP_AF23,    "Assured Forwarding 23" },
758                   { IPDSFIELD_DSCP_AF31,    "Assured Forwarding 31" },
759                   { IPDSFIELD_DSCP_AF32,    "Assured Forwarding 32" },
760                   { IPDSFIELD_DSCP_AF33,    "Assured Forwarding 33" },
761                   { IPDSFIELD_DSCP_AF41,    "Assured Forwarding 41" },
762                   { IPDSFIELD_DSCP_AF42,    "Assured Forwarding 42" },
763                   { IPDSFIELD_DSCP_AF43,    "Assured Forwarding 43" },
764                   { IPDSFIELD_DSCP_EF,      "Expedited Forwarding"  },
765                   { 0,                      NULL                    } };
766
767 static const value_string precedence_vals[] = {
768                   { IPTOS_PREC_ROUTINE,         "routine"              },
769                   { IPTOS_PREC_PRIORITY,        "priority"             },
770                   { IPTOS_PREC_IMMEDIATE,       "immediate"            },
771                   { IPTOS_PREC_FLASH,           "flash"                },
772                   { IPTOS_PREC_FLASHOVERRIDE,   "flash override"       },
773                   { IPTOS_PREC_CRITIC_ECP,      "CRITIC/ECP"           },
774                   { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
775                   { IPTOS_PREC_NETCONTROL,      "network control"      },
776                   { 0,                          NULL                   } };
777
778 static const value_string iptos_vals[] = {
779         { IPTOS_NONE,           "None" },
780         { IPTOS_LOWCOST,        "Minimize cost" },
781         { IPTOS_RELIABILITY,    "Maximize reliability" },
782         { IPTOS_THROUGHPUT,     "Maximize throughput" },
783         { IPTOS_LOWDELAY,       "Minimize delay" },
784         { IPTOS_SECURITY,       "Maximize security" },
785         { 0,                    NULL }
786 };
787
788 static const true_false_string tos_set_low = {
789   "Low",
790   "Normal"
791 };
792
793 static const true_false_string tos_set_high = {
794   "High",
795   "Normal"
796 };
797
798 static const true_false_string flags_set_truth = {
799   "Set",
800   "Not set"
801 };
802
803 static guint16 ip_checksum(const guint8 *ptr, int len)
804 {
805         vec_t cksum_vec[1];
806
807         cksum_vec[0].ptr = ptr;
808         cksum_vec[0].len = len;
809         return in_cksum(&cksum_vec[0], 1);
810 }
811
812 static void
813 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
814 {
815   e_ip       iph;
816   proto_tree *ip_tree = NULL, *field_tree;
817   proto_item *ti, *tf;
818   int        offset = 0;
819   guint      hlen, optlen, len;
820   guint16    flags;
821   guint8     nxt;
822   guint16    ipsum;
823   fragment_data *ipfd_head;
824   tvbuff_t   *next_tvb;
825   gboolean   update_col_info = TRUE;
826   gboolean   save_fragmented;
827
828   if (check_col(pinfo->cinfo, COL_PROTOCOL))
829     col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
830   if (check_col(pinfo->cinfo, COL_INFO))
831     col_clear(pinfo->cinfo, COL_INFO);
832
833   /* Avoids alignment problems on many architectures. */
834   tvb_memcpy(tvb, (guint8 *)&iph, offset, sizeof(e_ip));
835   iph.ip_len = ntohs(iph.ip_len);
836   iph.ip_id  = ntohs(iph.ip_id);
837   iph.ip_off = ntohs(iph.ip_off);
838   iph.ip_sum = ntohs(iph.ip_sum);
839
840   /* Length of IP datagram.
841      XXX - what if this is greater than the reported length of the
842      tvbuff?  This could happen, for example, in an IP datagram
843      inside an ICMP datagram; we need to somehow let the
844      dissector we call know that, as it might want to avoid
845      doing its checksumming. */
846   len = iph.ip_len;
847
848   /* Adjust the length of this tvbuff to include only the IP datagram. */
849   set_actual_length(tvb, len);
850
851   hlen = lo_nibble(iph.ip_v_hl) * 4;    /* IP header length, in bytes */
852  
853   if (tree) {
854     if (ip_summary_in_tree && hlen >= IPH_MIN_LEN) {
855       ti = proto_tree_add_protocol_format(tree, proto_ip, tvb, offset, hlen,
856                 "Internet Protocol, Src Addr: %s (%s), Dst Addr: %s (%s)",
857                 get_hostname(iph.ip_src), ip_to_str((guint8 *) &iph.ip_src),
858                 get_hostname(iph.ip_dst), ip_to_str((guint8 *) &iph.ip_dst));
859     } else {
860       ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
861     }
862     ip_tree = proto_item_add_subtree(ti, ett_ip);
863   }
864
865   if (hlen < IPH_MIN_LEN) {
866     if (check_col(pinfo->cinfo, COL_INFO))
867       col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
868        hlen, IPH_MIN_LEN);
869     if (tree) {
870       proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
871        "Header length: %u bytes (bogus, must be at least %u)", hlen,
872        IPH_MIN_LEN);
873     }
874     return;
875   }
876
877   /*
878    * Compute the checksum of the IP header.
879    */
880   ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
881
882   if (tree) {
883     proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1, hi_nibble(iph.ip_v_hl));
884     proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
885         "Header length: %u bytes", hlen);
886
887     if (g_ip_dscp_actif) {
888       tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph.ip_tos,
889            "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph.ip_tos,
890            IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
891            "Unknown DSCP"),IPDSFIELD_ECN(iph.ip_tos));
892
893       field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
894       proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph.ip_tos);
895       proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph.ip_tos);
896       proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph.ip_tos);
897     } else {
898       tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph.ip_tos,
899           "Type of service: 0x%02x (%s)", iph.ip_tos,
900           val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
901
902       field_tree = proto_item_add_subtree(tf, ett_ip_tos);
903       proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph.ip_tos);
904       proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph.ip_tos);
905       proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph.ip_tos);
906       proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph.ip_tos);
907       proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph.ip_tos);
908     }
909     proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset +  2, 2, iph.ip_len);
910     proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset +  4, 2, iph.ip_id);
911
912     flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
913     tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset +  6, 1, flags);
914     field_tree = proto_item_add_subtree(tf, ett_ip_off);
915     proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
916     proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
917
918     proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset +  6, 2,
919       (iph.ip_off & IP_OFFSET)*8);
920
921     proto_tree_add_uint(ip_tree, hf_ip_ttl, tvb, offset +  8, 1, iph.ip_ttl);
922     proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset +  9, 1, iph.ip_p,
923         "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
924
925     if (ipsum == 0) {
926         proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
927               "Header checksum: 0x%04x (correct)", iph.ip_sum);
928     }
929     else {
930         proto_tree_add_boolean_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
931         proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
932           "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph.ip_sum,
933           in_cksum_shouldbe(iph.ip_sum, ipsum));
934     }
935
936     proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, iph.ip_src);
937     proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, iph.ip_dst);
938     proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, iph.ip_src);
939     proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, iph.ip_dst);
940
941     /* Decode IP options, if any. */
942     if (hlen > sizeof (e_ip)) {
943       /* There's more than just the fixed-length header.  Decode the
944          options. */
945       optlen = hlen - sizeof (e_ip);    /* length of options, in bytes */
946       tf = proto_tree_add_text(ip_tree, tvb, offset +  20, optlen,
947         "Options: (%u bytes)", optlen);
948       field_tree = proto_item_add_subtree(tf, ett_ip_options);
949       dissect_ip_tcp_options(tvb, offset + 20, optlen,
950          ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
951     }
952   }
953
954   pinfo->ipproto = iph.ip_p;
955
956   pinfo->iplen = iph.ip_len;
957
958   pinfo->iphdrlen = lo_nibble(iph.ip_v_hl);
959
960   SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
961   SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
962   SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
963   SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
964
965   /* Skip over header + options */
966   offset += hlen;
967   nxt = iph.ip_p;       /* XXX - what if this isn't the same for all fragments? */
968
969   /* If ip_defragment is on, this is a fragment, we have all the data
970    * in the fragment, and the header checksum is valid, then just add
971    * the fragment to the hashtable.
972    */
973   save_fragmented = pinfo->fragmented;
974   if (ip_defragment && (iph.ip_off & (IP_MF|IP_OFFSET)) &&
975         tvb_reported_length(tvb) <= tvb_length(tvb) && ipsum == 0) {
976     ipfd_head = fragment_add(tvb, offset, pinfo, iph.ip_id,
977                              ip_fragment_table,
978                              (iph.ip_off & IP_OFFSET)*8,
979                              pinfo->iplen - (pinfo->iphdrlen*4),
980                              iph.ip_off & IP_MF);
981
982     if (ipfd_head != NULL) {
983       fragment_data *ipfd;
984       proto_tree *ft=NULL;
985       proto_item *fi=NULL;
986
987       /* OK, we have the complete reassembled payload. */
988       /* show all fragments */
989       fi = proto_tree_add_item(ip_tree, hf_ip_fragments, 
990                 tvb, 0, 0, FALSE);
991       ft = proto_item_add_subtree(fi, ett_ip_fragments);
992       for (ipfd=ipfd_head->next; ipfd; ipfd=ipfd->next){
993         if (ipfd->flags & (FD_OVERLAP|FD_OVERLAPCONFLICT
994                           |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
995           /* this fragment has some flags set, create a subtree 
996            * for it and display the flags.
997            */
998           proto_tree *fet=NULL;
999           proto_item *fei=NULL;
1000           int hf;
1001
1002           if (ipfd->flags & (FD_OVERLAPCONFLICT
1003                       |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
1004             hf = hf_ip_fragment_error;
1005           } else {
1006             hf = hf_ip_fragment;
1007           }
1008           fei = proto_tree_add_none_format(ft, hf, 
1009                    tvb, 0, 0,
1010                    "Frame:%u payload:%u-%u",
1011                    ipfd->frame,
1012                    ipfd->offset,
1013                    ipfd->offset+ipfd->len-1
1014           );
1015           fet = proto_item_add_subtree(fei, ett_ip_fragment);
1016           if (ipfd->flags&FD_OVERLAP) {
1017             proto_tree_add_boolean(fet, 
1018                  hf_ip_fragment_overlap, tvb, 0, 0, 
1019                  TRUE);
1020           }
1021           if (ipfd->flags&FD_OVERLAPCONFLICT) {
1022             proto_tree_add_boolean(fet, 
1023                  hf_ip_fragment_overlap_conflict, tvb, 0, 0, 
1024                  TRUE);
1025           }
1026           if (ipfd->flags&FD_MULTIPLETAILS) {
1027             proto_tree_add_boolean(fet, 
1028                  hf_ip_fragment_multiple_tails, tvb, 0, 0, 
1029                  TRUE);
1030           }
1031           if (ipfd->flags&FD_TOOLONGFRAGMENT) {
1032             proto_tree_add_boolean(fet, 
1033                  hf_ip_fragment_too_long_fragment, tvb, 0, 0, 
1034                  TRUE);
1035           }
1036         } else {
1037           /* nothing of interest for this fragment */
1038           proto_tree_add_none_format(ft, hf_ip_fragment, 
1039                    tvb, 0, 0,
1040                    "Frame:%u payload:%u-%u",
1041                    ipfd->frame,
1042                    ipfd->offset,
1043                    ipfd->offset+ipfd->len-1
1044           );
1045         }
1046       }
1047       if (ipfd_head->flags & (FD_OVERLAPCONFLICT
1048                         |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
1049         if (check_col(pinfo->cinfo, COL_INFO)) {
1050           col_set_str(pinfo->cinfo, COL_INFO, "[Illegal fragments]");
1051           update_col_info = FALSE;
1052         }
1053       }
1054
1055       /* Allocate a new tvbuff, referring to the reassembled payload. */
1056       next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen,
1057         ipfd_head->datalen);
1058
1059       /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
1060          were handed refers, so it'll get cleaned up when that tvbuff
1061          is cleaned up. */
1062       tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1063
1064       /* Add the defragmented data to the data source list. */
1065       add_new_data_source(pinfo->fd, next_tvb, "Reassembled IPv4");
1066
1067       /* It's not fragmented. */
1068       pinfo->fragmented = FALSE;
1069     } else {
1070       /* We don't have the complete reassembled payload. */
1071       next_tvb = NULL;
1072     }
1073   } else {
1074     /* If this is the first fragment, dissect its contents, otherwise
1075        just show it as a fragment.
1076
1077        XXX - if we eventually don't save the reassembled contents of all
1078        fragmented datagrams, we may want to always reassemble. */
1079     if (iph.ip_off & IP_OFFSET) {
1080       /* Not the first fragment - don't dissect it. */
1081       next_tvb = NULL;
1082     } else {
1083       /* First fragment, or not fragmented.  Dissect what we have here. */
1084
1085       /* Get a tvbuff for the payload. */
1086       next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1087
1088       /*
1089        * If this is the first fragment, but not the only fragment,
1090        * tell the next protocol that.
1091        */
1092       if (iph.ip_off & IP_MF)
1093         pinfo->fragmented = TRUE;
1094       else
1095         pinfo->fragmented = FALSE;
1096     }
1097   }
1098
1099   if (next_tvb == NULL) {
1100     /* Just show this as a fragment. */
1101     if (check_col(pinfo->cinfo, COL_INFO))
1102       col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1103         ipprotostr(iph.ip_p), iph.ip_p, (iph.ip_off & IP_OFFSET) * 8);
1104     call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, tree);
1105     pinfo->fragmented = save_fragmented;
1106     return;
1107   }
1108
1109   /* Hand off to the next protocol.
1110
1111      XXX - setting the columns only after trying various dissectors means
1112      that if one of those dissectors throws an exception, the frame won't
1113      even be labelled as an IP frame; ideally, if a frame being dissected
1114      throws an exception, it'll be labelled as a mangled frame of the
1115      type in question. */
1116   if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
1117     /* Unknown protocol */
1118     if (update_col_info) {
1119       if (check_col(pinfo->cinfo, COL_INFO))
1120         col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
1121     }
1122     call_dissector(data_handle,next_tvb, pinfo, tree);
1123   }
1124   pinfo->fragmented = save_fragmented;
1125 }
1126
1127 #define ICMP_MIP_EXTENSION_PAD  0
1128 #define ICMP_MIP_MOB_AGENT_ADV  16
1129 #define ICMP_MIP_PREFIX_LENGTHS 19
1130 #define ICMP_MIP_CHALLENGE      24
1131
1132 static value_string mip_extensions[] = {
1133   { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"},  /* RFC 2002 */
1134   { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1135                                                             /* RFC 2002 */
1136   { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"},   /* RFC 2002 */
1137   { ICMP_MIP_CHALLENGE, "Challenge Extension"},             /* RFC 3012 */
1138   { 0, NULL}
1139 };
1140
1141 /*
1142  * Dissect the mobile ip advertisement extensions.
1143  */
1144 static void
1145 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, packet_info *pinfo,
1146                                            proto_tree *tree)
1147 {
1148   guint8       type;
1149   guint8       length;
1150   guint8       flags;
1151   proto_item   *ti;
1152   proto_tree   *mip_tree=NULL;
1153   proto_tree   *flags_tree=NULL;
1154   gint         numCOAs;
1155   gint         i;
1156
1157   /* Not much to do if we're not parsing everything */
1158   if (!tree) return;
1159   
1160   while ((tvb_length(tvb) - offset) > 0) {
1161
1162         type = tvb_get_guint8(tvb, offset + 0);
1163         if (type)
1164           length = tvb_get_guint8(tvb, offset + 1);
1165         else
1166           length=0;
1167
1168         ti = proto_tree_add_text(tree, tvb, offset,
1169                                                          type?(length + 2):1,
1170                                                          "Ext: %s",
1171                                                          val_to_str(type, mip_extensions,
1172                                                                                 "Unknown ext %u"));
1173         mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1174   
1175
1176         switch (type) {
1177         case ICMP_MIP_EXTENSION_PAD:
1178           /* One byte padding extension */
1179           /* Add our fields */
1180           /* type */
1181           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset, 
1182                                                   1, FALSE);
1183           offset++;
1184           break;
1185         case ICMP_MIP_MOB_AGENT_ADV:
1186           /* Mobility Agent Advertisement Extension (RFC 2002)*/
1187           /* Add our fields */
1188           /* type */
1189           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset, 
1190                                                   1, FALSE);
1191           offset++;
1192           /* length */
1193           proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset, 
1194                                                   1, FALSE);
1195           offset++;
1196           /* sequence number */
1197           proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset, 
1198                                                   2, FALSE);
1199           offset+=2;
1200           /* Registration Lifetime */
1201           proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset, 
1202                                                   2, FALSE);
1203           offset+=2;
1204           /* flags */
1205           flags = tvb_get_guint8(tvb, offset);
1206           ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1207                                                            1, FALSE);
1208           flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1209           proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1210           proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1211           proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1212           proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1213           proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1214           proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1215           proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1216           proto_tree_add_boolean(flags_tree, hf_icmp_mip_res, tvb, offset, 1, flags);
1217           offset++;
1218           
1219           /* Reserved */
1220           proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset, 
1221                                                   1, FALSE);
1222           offset++;
1223           
1224           /* COAs */
1225           numCOAs = (length - 6) / 4;
1226           for (i=0; i<numCOAs; i++) {
1227                 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset, 
1228                                                         4, FALSE);
1229                 offset+=4;
1230           }
1231           break;
1232         case ICMP_MIP_PREFIX_LENGTHS:
1233           /* Prefix-Lengths Extension  (RFC 2002)*/
1234           /* Add our fields */
1235           /* type */
1236           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset, 
1237                                                   1, FALSE);
1238           offset++;
1239           /* length */
1240           proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset, 
1241                                                   1, FALSE);
1242           offset++;
1243
1244           /* prefix lengths */
1245           for(i=0; i<length; i++) {
1246                 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1247                                                         1, FALSE);
1248                 offset++;
1249           }
1250           break;
1251         case ICMP_MIP_CHALLENGE:
1252           /* Challenge Extension  (RFC 3012)*/
1253           /* type */
1254           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset, 
1255                                                   1, FALSE);
1256           offset++;
1257           /* length */
1258           proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset, 
1259                                                   1, FALSE);
1260           offset++;
1261           /* challenge */
1262           proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset, 
1263                                                   length, FALSE);
1264           offset+=length;
1265           
1266           break;
1267         default:
1268           g_warning("Unknown type(%u)!  I hope the length is right (%u)",
1269                                 type, length);
1270           offset += length;
1271           break;
1272         } /* switch type */
1273   } /* end while */
1274   
1275 } /* dissect_mip_extensions */
1276
1277 static const gchar *unreach_str[] = {"Network unreachable",
1278                                      "Host unreachable",
1279                                      "Protocol unreachable",
1280                                      "Port unreachable",
1281                                      "Fragmentation needed",
1282                                      "Source route failed",
1283                                      "Destination network unknown",
1284                                      "Destination host unknown",
1285                                      "Source host isolated",
1286                                      "Network administratively prohibited",
1287                                      "Host administratively prohibited",
1288                                      "Network unreachable for TOS",
1289                                      "Host unreachable for TOS",
1290                                      "Communication administratively filtered",
1291                                      "Host precedence violation",
1292                                      "Precedence cutoff in effect"};
1293                                      
1294 #define N_UNREACH       (sizeof unreach_str / sizeof unreach_str[0])
1295
1296 static const gchar *redir_str[] = {"Redirect for network",
1297                                    "Redirect for host",
1298                                    "Redirect for TOS and network",
1299                                    "Redirect for TOS and host"};
1300
1301 #define N_REDIRECT      (sizeof redir_str / sizeof redir_str[0])
1302
1303 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
1304                                  "TTL equals 0 during reassembly"};
1305                                  
1306 #define N_TIMXCEED      (sizeof ttl_str / sizeof ttl_str[0])
1307
1308 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1309
1310 #define N_PARAMPROB     (sizeof par_str / sizeof par_str[0])
1311
1312 /*
1313  * RFC 792 for basic ICMP.
1314  * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1315  * RFC 1256 for router discovery messages.
1316  * RFC 2002 and 3012 for Mobile IP stuff.
1317  */
1318 static void
1319 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1320 {
1321   proto_tree *icmp_tree;
1322   proto_item *ti;
1323   guint8     icmp_type;
1324   guint8     icmp_code;
1325   guint      length, reported_length;
1326   guint16    cksum, computed_cksum;
1327   gchar      type_str[64], code_str[64] = "";
1328   guint8     num_addrs = 0;
1329   guint8     addr_entry_size = 0;
1330   int        i;
1331   volatile address save_dl_src;
1332   volatile address save_dl_dst;
1333   volatile address save_net_src;
1334   volatile address save_net_dst;
1335   volatile address save_src;
1336   volatile address save_dst;
1337   gboolean   save_in_error_pkt;
1338   tvbuff_t   *next_tvb;
1339
1340   if (check_col(pinfo->cinfo, COL_PROTOCOL))
1341     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1342   if (check_col(pinfo->cinfo, COL_INFO))
1343     col_clear(pinfo->cinfo, COL_INFO);
1344
1345   /* To do: check for runts, errs, etc. */
1346   icmp_type = tvb_get_guint8(tvb, 0);
1347   icmp_code = tvb_get_guint8(tvb, 1);
1348   cksum = tvb_get_ntohs(tvb, 2);
1349
1350   switch (icmp_type) {
1351     case ICMP_ECHOREPLY:
1352       strcpy(type_str, "Echo (ping) reply");
1353       break;
1354     case ICMP_UNREACH:
1355       strcpy(type_str, "Destination unreachable");
1356       if (icmp_code < N_UNREACH) {
1357         sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1358       } else {
1359         strcpy(code_str, "(Unknown - error?)");
1360       }
1361       break;
1362     case ICMP_SOURCEQUENCH:
1363       strcpy(type_str, "Source quench (flow control)");
1364       break;
1365     case ICMP_REDIRECT:
1366       strcpy(type_str, "Redirect");
1367       if (icmp_code < N_REDIRECT) {
1368         sprintf(code_str, "(%s)", redir_str[icmp_code]);
1369       } else {
1370         strcpy(code_str, "(Unknown - error?)");
1371       }
1372       break;
1373     case ICMP_ECHO:
1374       strcpy(type_str, "Echo (ping) request");
1375       break;
1376     case ICMP_RTRADVERT:
1377       switch (icmp_code) {
1378       case 16: /* Mobile-Ip */
1379         strcpy(type_str, "Mobile IP Advertisement");
1380         break;
1381       default:
1382         strcpy(type_str, "Router advertisement");
1383         break;
1384       } /* switch icmp_code */
1385       break;
1386     case ICMP_RTRSOLICIT:
1387       strcpy(type_str, "Router solicitation");
1388       break;
1389     case ICMP_TIMXCEED:
1390       strcpy(type_str, "Time-to-live exceeded");
1391       if (icmp_code < N_TIMXCEED) {
1392         sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1393       } else {
1394         strcpy(code_str, "(Unknown - error?)");
1395       }
1396       break;
1397     case ICMP_PARAMPROB:
1398       strcpy(type_str, "Parameter problem");
1399       if (icmp_code < N_PARAMPROB) {
1400         sprintf(code_str, "(%s)", par_str[icmp_code]);
1401       } else {
1402         strcpy(code_str, "(Unknown - error?)");
1403       }
1404       break;
1405     case ICMP_TSTAMP:
1406       strcpy(type_str, "Timestamp request");
1407       break;
1408     case ICMP_TSTAMPREPLY:
1409       strcpy(type_str, "Timestamp reply");
1410       break;
1411     case ICMP_IREQ:
1412       strcpy(type_str, "Information request");
1413       break;
1414     case ICMP_IREQREPLY:
1415       strcpy(type_str, "Information reply");
1416       break;
1417     case ICMP_MASKREQ:
1418       strcpy(type_str, "Address mask request");
1419       break;
1420     case ICMP_MASKREPLY:
1421       strcpy(type_str, "Address mask reply");
1422       break;
1423     default:
1424       strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1425       break;
1426   }
1427
1428   if (check_col(pinfo->cinfo, COL_INFO))
1429     col_add_str(pinfo->cinfo, COL_INFO, type_str);
1430
1431   if (tree) {
1432     length = tvb_length(tvb);
1433     reported_length = tvb_reported_length(tvb);
1434     ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1435     icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1436     proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1, 
1437                                icmp_type,
1438                                "Type: %u (%s)",
1439                                icmp_type, type_str);
1440     proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1, 
1441                                icmp_code,
1442                                "Code: %u %s",
1443                                icmp_code, code_str);
1444
1445     if (!pinfo->fragmented && length >= reported_length) {
1446       /* The packet isn't part of a fragmented datagram and isn't
1447          truncated, so we can checksum it. */
1448
1449       computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1450                                      reported_length);
1451       if (computed_cksum == 0) {
1452         proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1453                           cksum,
1454                           "Checksum: 0x%04x (correct)", cksum);
1455       } else {
1456         proto_tree_add_boolean_hidden(icmp_tree, hf_icmp_checksum_bad,
1457                           tvb, 2, 2, TRUE);
1458         proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1459                   cksum,
1460                   "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1461                   cksum, in_cksum_shouldbe(cksum, computed_cksum));
1462       }
1463     } else {
1464       proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1465     }
1466
1467     /* Decode the second 4 bytes of the packet. */
1468     switch (icmp_type) {
1469       case ICMP_ECHOREPLY:
1470       case ICMP_ECHO:
1471       case ICMP_TSTAMP:
1472       case ICMP_TSTAMPREPLY:
1473       case ICMP_IREQ:
1474       case ICMP_IREQREPLY:
1475       case ICMP_MASKREQ:
1476       case ICMP_MASKREPLY:
1477         proto_tree_add_text(icmp_tree, tvb, 4, 2, "Identifier: 0x%04x",
1478           tvb_get_ntohs(tvb, 4));
1479         proto_tree_add_text(icmp_tree, tvb, 6, 2, "Sequence number: %02x:%02x",
1480           tvb_get_guint8(tvb, 6), tvb_get_guint8(tvb, 7));
1481         break;
1482
1483       case ICMP_UNREACH:
1484         switch (icmp_code) {
1485           case ICMP_FRAG_NEEDED:
1486             proto_tree_add_text(icmp_tree, tvb, 6, 2, "MTU of next hop: %u",
1487                   tvb_get_ntohs(tvb, 6));
1488             break;
1489         }
1490         break;
1491
1492       case ICMP_RTRADVERT:
1493         num_addrs = tvb_get_guint8(tvb, 4);
1494         proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1495           num_addrs);
1496         addr_entry_size = tvb_get_guint8(tvb, 5);
1497         proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1498           addr_entry_size);
1499         proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1500           time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1501         break;
1502
1503       case ICMP_PARAMPROB:
1504         proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1505           tvb_get_guint8(tvb, 4));
1506         break;
1507
1508       case ICMP_REDIRECT:
1509         proto_tree_add_text(icmp_tree, tvb, 4, 4, "Gateway address: %s",
1510           ip_to_str(tvb_get_ptr(tvb, 4, 4)));
1511         break;
1512     }
1513
1514     /* Decode the additional information in the packet.  */
1515     switch (icmp_type) {
1516       case ICMP_UNREACH:
1517       case ICMP_TIMXCEED:
1518       case ICMP_PARAMPROB:
1519       case ICMP_SOURCEQUENCH:
1520       case ICMP_REDIRECT:
1521         /* Decode the IP header and first 64 bits of data from the
1522            original datagram.
1523
1524            Set the columns non-writable, so that the packet list
1525            shows this as an ICMP packet, not as the type of packet
1526            for which the ICMP packet was generated. */
1527         col_set_writable(pinfo->cinfo, FALSE);
1528
1529         /* Also, save the current values of the addresses, and restore
1530            them when we're finished dissecting the contained packet, so
1531            that the address columns in the summary don't reflect the
1532            contained packet, but reflect this packet instead. */
1533         save_dl_src = pinfo->dl_src;
1534         save_dl_dst = pinfo->dl_dst;
1535         save_net_src = pinfo->net_src;
1536         save_net_dst = pinfo->net_dst;
1537         save_src = pinfo->src;
1538         save_dst = pinfo->dst;
1539
1540         /* Save the current value of the "we're inside an error packet"
1541            flag, and set that flag; subdissectors may treat packets
1542            that are the payload of error packets differently from
1543            "real" packets. */
1544         save_in_error_pkt = pinfo->in_error_pkt;
1545         pinfo->in_error_pkt = TRUE;
1546
1547         /* Dissect the contained packet.
1548            Catch ReportedBoundsError, and do nothing if we see it,
1549            because it's not an error if the contained packet is short;
1550            there's no guarantee that all of it was included.
1551
1552            XXX - should catch BoundsError, and re-throw it after cleaning
1553            up. */
1554         next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1555         TRY {
1556           call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1557         }
1558         CATCH(ReportedBoundsError) {
1559           ; /* do nothing */
1560         }
1561         ENDTRY;
1562
1563         /* Restore the "we're inside an error packet" flag. */
1564         pinfo->in_error_pkt = save_in_error_pkt;
1565
1566         /* Restore the addresses. */
1567         pinfo->dl_src = save_dl_src;
1568         pinfo->dl_dst = save_dl_dst;
1569         pinfo->net_src = save_net_src;
1570         pinfo->net_dst = save_net_dst;
1571         pinfo->src = save_src;
1572         pinfo->dst = save_dst;
1573         break;
1574
1575       case ICMP_ECHOREPLY:
1576       case ICMP_ECHO:
1577         call_dissector(data_handle,tvb_new_subset(tvb, 8,-1,tvb_reported_length_remaining(tvb,8)), pinfo, icmp_tree);
1578         break;
1579
1580       case ICMP_RTRADVERT:
1581         if (addr_entry_size == 2) {
1582           for (i = 0; i < num_addrs; i++) {
1583             proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1584               "Router address: %s",
1585               ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1586             proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1587               "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1588           }
1589           if (icmp_code == 16) {
1590                 /* Mobile-Ip */
1591                 dissect_mip_extensions(tvb,8 + i*8, pinfo, icmp_tree);
1592           }
1593         } else
1594           call_dissector(data_handle,tvb_new_subset(tvb, 8,-1,tvb_reported_length_remaining(tvb,8)), pinfo, icmp_tree);
1595         break;
1596
1597       case ICMP_TSTAMP:
1598       case ICMP_TSTAMPREPLY:
1599         proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1600           tvb_get_ntohl(tvb, 8));
1601         proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1602           tvb_get_ntohl(tvb, 12));
1603         proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1604           tvb_get_ntohl(tvb, 16));
1605         break;
1606
1607     case ICMP_MASKREQ:
1608     case ICMP_MASKREPLY:
1609         proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1610           ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1611         break;
1612     }
1613   }
1614 }
1615
1616 void
1617 proto_register_ip(void)
1618 {
1619         static hf_register_info hf[] = {
1620
1621                 { &hf_ip_version,
1622                 { "Version",            "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1623                         "", HFILL }},
1624
1625                 { &hf_ip_hdr_len,
1626                 { "Header Length",      "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1627                         "", HFILL }},
1628
1629                 { &hf_ip_dsfield,
1630                 { "Differentiated Services field",      "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1631                         "", HFILL }},
1632
1633                 { &hf_ip_dsfield_dscp,
1634                 { "Differentiated Services Codepoint",  "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1635                         VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1636                         "", HFILL }},
1637
1638                 { &hf_ip_dsfield_ect,
1639                 { "ECN-Capable Transport (ECT)",        "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1640                         IPDSFIELD_ECT_MASK,
1641                         "", HFILL }},
1642
1643                 { &hf_ip_dsfield_ce,
1644                 { "ECN-CE",     "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1645                         IPDSFIELD_CE_MASK,
1646                         "", HFILL }},
1647
1648                 { &hf_ip_tos,
1649                 { "Type of Service",    "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1650                         "", HFILL }},
1651
1652                 { &hf_ip_tos_precedence,
1653                 { "Precedence",         "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1654                         IPTOS_PREC_MASK,
1655                         "", HFILL }},
1656
1657                 { &hf_ip_tos_delay,
1658                 { "Delay",              "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1659                         IPTOS_LOWDELAY,
1660                         "", HFILL }},
1661
1662                 { &hf_ip_tos_throughput,
1663                 { "Throughput",         "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1664                         IPTOS_THROUGHPUT,
1665                         "", HFILL }},
1666
1667                 { &hf_ip_tos_reliability,
1668                 { "Reliability",        "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1669                         IPTOS_RELIABILITY,
1670                         "", HFILL }},
1671
1672                 { &hf_ip_tos_cost,
1673                 { "Cost",               "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1674                         IPTOS_LOWCOST,
1675                         "", HFILL }},
1676
1677                 { &hf_ip_len,
1678                 { "Total Length",       "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1679                         "", HFILL }},
1680
1681                 { &hf_ip_id,
1682                 { "Identification",     "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1683                         "", HFILL }},
1684
1685                 { &hf_ip_dst,
1686                 { "Destination",        "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1687                         "", HFILL }},
1688
1689                 { &hf_ip_src,
1690                 { "Source",             "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1691                         "", HFILL }},
1692
1693                 { &hf_ip_addr,
1694                 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1695                         "", HFILL }},
1696
1697                 { &hf_ip_flags,
1698                 { "Flags",              "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1699                         "", HFILL }},
1700
1701                 { &hf_ip_flags_df,
1702                 { "Don't fragment",     "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1703                         "", HFILL }},
1704
1705                 { &hf_ip_flags_mf,
1706                 { "More fragments",     "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1707                         "", HFILL }},
1708
1709                 { &hf_ip_frag_offset,
1710                 { "Fragment offset",    "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1711                         "", HFILL }},
1712
1713                 { &hf_ip_ttl,
1714                 { "Time to live",       "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1715                         "", HFILL }},
1716
1717                 { &hf_ip_proto,
1718                 { "Protocol",           "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1719                         "", HFILL }},
1720
1721                 { &hf_ip_checksum,
1722                 { "Header checksum",    "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1723                         "", HFILL }},
1724
1725                 { &hf_ip_checksum_bad,
1726                 { "Bad Header checksum",        "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1727                         "", HFILL }},
1728
1729                 { &hf_ip_fragment_overlap,
1730                 { "Fragment overlap",   "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1731                         "Fragment overlaps with other fragments", HFILL }},
1732
1733                 { &hf_ip_fragment_overlap_conflict,
1734                 { "Conflicting data in fragment overlap",       "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1735                         "Overlapping fragments contained conflicting data", HFILL }},
1736
1737                 { &hf_ip_fragment_multiple_tails,
1738                 { "Multiple tail fragments found",      "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1739                         "Several tails were found when defragmenting the packet", HFILL }},
1740
1741                 { &hf_ip_fragment_too_long_fragment,
1742                 { "Fragment too long",  "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1743                         "Fragment contained data past end of packet", HFILL }},
1744
1745                 { &hf_ip_fragment_error,
1746                 { "Defragmentation error", "ip.fragment.error", FT_NONE, BASE_NONE, NULL, 0x0,
1747                         "Defragmentation error due to illegal fragments", HFILL }},
1748
1749                 { &hf_ip_fragment,
1750                 { "IP Fragment", "ip.fragment", FT_NONE, BASE_NONE, NULL, 0x0,
1751                         "IP Fragment", HFILL }},
1752
1753                 { &hf_ip_fragments,
1754                 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1755                         "IP Fragments", HFILL }},
1756         };
1757         static gint *ett[] = {
1758                 &ett_ip,
1759                 &ett_ip_dsfield,
1760                 &ett_ip_tos,
1761                 &ett_ip_off,
1762                 &ett_ip_options,
1763                 &ett_ip_option_sec,
1764                 &ett_ip_option_route,
1765                 &ett_ip_option_timestamp,
1766                 &ett_ip_fragments,
1767                 &ett_ip_fragment,
1768         };
1769         module_t *ip_module;
1770
1771         proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1772         proto_register_field_array(proto_ip, hf, array_length(hf));
1773         proto_register_subtree_array(ett, array_length(ett));
1774
1775         /* subdissector code */
1776         ip_dissector_table = register_dissector_table("ip.proto",
1777             "IP protocol", FT_UINT8, BASE_DEC);
1778
1779         /* Register configuration options */
1780         ip_module = prefs_register_protocol(proto_ip, NULL);
1781         prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1782             "Decode IPv4 TOS field as DiffServ field",
1783             "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1784             &g_ip_dscp_actif);
1785         prefs_register_bool_preference(ip_module, "defragment",
1786                 "Reassemble fragmented IP datagrams",
1787                 "Whether fragmented IP datagrams should be reassembled",
1788                 &ip_defragment);
1789         prefs_register_bool_preference(ip_module, "ip_summary_in_tree",
1790             "Show IP summary in protocol tree",
1791             "Whether the IP summary line should be shown in the protocol tree",
1792             &ip_summary_in_tree);
1793
1794         register_dissector("ip", dissect_ip, proto_ip);
1795         register_init_routine(ip_defragment_init);
1796 }
1797
1798 void
1799 proto_reg_handoff_ip(void)
1800 {
1801         dissector_handle_t ip_handle;
1802
1803         data_handle = find_dissector("data");
1804         ip_handle = find_dissector("ip");
1805         dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
1806         dissector_add("ppp.protocol", PPP_IP, ip_handle);
1807         dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
1808         dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
1809         dissector_add("gre.proto", GRE_WCCP, ip_handle);
1810         dissector_add("llc.dsap", SAP_IP, ip_handle);
1811         dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
1812         dissector_add("null.type", BSD_AF_INET, ip_handle);
1813         dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
1814         dissector_add("fr.ietf", NLPID_IP, ip_handle);
1815         dissector_add("x.25.spi", NLPID_IP, ip_handle);
1816 }
1817
1818 void
1819 proto_register_icmp(void)
1820 {
1821   static hf_register_info hf[] = {
1822     
1823     { &hf_icmp_type,
1824       { "Type",         "icmp.type",            FT_UINT8, BASE_DEC,     NULL, 0x0,
1825         "", HFILL }},
1826
1827     { &hf_icmp_code,
1828       { "Code",         "icmp.code",            FT_UINT8, BASE_HEX,     NULL, 0x0,
1829         "", HFILL }},    
1830
1831     { &hf_icmp_checksum,
1832       { "Checksum",     "icmp.checksum",        FT_UINT16, BASE_HEX,    NULL, 0x0,
1833         "", HFILL }},
1834
1835     { &hf_icmp_checksum_bad,
1836       { "Bad Checksum", "icmp.checksum_bad",    FT_BOOLEAN, BASE_NONE,  NULL, 0x0,
1837         "", HFILL }},
1838
1839     { &hf_icmp_mip_type,
1840       { "Extension Type", "icmp.mip.type",      FT_UINT8, BASE_DEC,
1841         VALS(mip_extensions), 0x0,"", HFILL}},
1842
1843     { &hf_icmp_mip_length,
1844       { "Length", "icmp.mip.length",            FT_UINT8, BASE_DEC, NULL, 0x0,
1845         "", HFILL}},
1846
1847     { &hf_icmp_mip_prefix_length,
1848       { "Prefix Length", "icmp.mip.prefixlength",  FT_UINT8, BASE_DEC, NULL, 0x0,
1849         "", HFILL}},
1850
1851     { &hf_icmp_mip_seq,
1852       { "Sequence Number", "icmp.mip.seq",      FT_UINT16, BASE_DEC, NULL, 0x0,
1853         "", HFILL}},
1854
1855     { &hf_icmp_mip_life,
1856       { "Registration Lifetime", "icmp.mip.life",  FT_UINT16, BASE_DEC, NULL, 0x0,
1857         "", HFILL}},
1858
1859     { &hf_icmp_mip_flags,
1860       { "Flags", "icmp.mip.flags",            FT_UINT8, BASE_HEX, NULL, 0x0,
1861         "", HFILL}},
1862
1863     { &hf_icmp_mip_r,
1864       { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
1865         "Registration with this FA is required", HFILL }},
1866
1867     { &hf_icmp_mip_b,
1868       { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
1869         "This FA will not accept requests at this time", HFILL }},
1870
1871     { &hf_icmp_mip_h,
1872       { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
1873         "Home Agent Services Offered", HFILL }},
1874
1875     { &hf_icmp_mip_f,
1876       { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
1877         "Foreign Agent Services Offered", HFILL }},
1878
1879     { &hf_icmp_mip_m,
1880       { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
1881         "Minimal encapsulation tunneled datagram support", HFILL }},
1882
1883     { &hf_icmp_mip_g,
1884       { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
1885         "GRE encapsulated tunneled datagram support", HFILL }},
1886
1887     { &hf_icmp_mip_v,
1888       { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
1889         "Van Jacobson Header Compression Support", HFILL }},
1890
1891     { &hf_icmp_mip_res,
1892       { "Reserved", "icmp.mip.res", FT_BOOLEAN, 8, NULL, 1,
1893         "Reserved", HFILL }},
1894
1895     { &hf_icmp_mip_reserved,
1896       { "Reserved", "icmp.mip.reserved",     FT_UINT8, BASE_HEX, NULL, 0x0,
1897         "", HFILL}},
1898
1899     { &hf_icmp_mip_coa,
1900       { "Care-Of-Address", "icmp.mip.coa",    FT_IPv4, BASE_NONE, NULL, 0x0,
1901         "", HFILL}},
1902
1903     { &hf_icmp_mip_challenge,
1904       { "Challenge", "icmp.mip.challenge",    FT_BYTES, BASE_NONE, NULL, 0x0,
1905         "", HFILL}},
1906   };
1907   static gint *ett[] = {
1908     &ett_icmp,
1909         &ett_icmp_mip,
1910         &ett_icmp_mip_flags
1911   };
1912   
1913   proto_icmp = proto_register_protocol("Internet Control Message Protocol", 
1914                                        "ICMP", "icmp");
1915   proto_register_field_array(proto_icmp, hf, array_length(hf));
1916   proto_register_subtree_array(ett, array_length(ett));
1917 }
1918
1919 void
1920 proto_reg_handoff_icmp(void)
1921 {
1922   dissector_handle_t icmp_handle;
1923
1924   /*
1925    * Get handle for the IP dissector.
1926    */
1927   ip_handle = find_dissector("ip");
1928
1929   icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
1930   dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);
1931 }