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