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