Stephen Fisher:
[obnox/wireshark/wip.git] / epan / dissectors / packet-ip.c
1 /* packet-ip.c
2  * Routines for IP and miscellaneous IP protocol packet disassembly
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * Monday, June 27, 2005
11  * Support for the ICMP extensions for MPLS
12  * (http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt)
13  * by   Maria-Luiza Crivat <luizacri@gmail.com>
14  * &    Brice Augustin <bricecotte@gmail.com>
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <glib.h>
38
39 #include <epan/packet.h>
40 #include <epan/addr_resolv.h>
41 #include <epan/ipproto.h>
42 #include <epan/ip_opts.h>
43 #include <epan/prefs.h>
44 #include <epan/reassemble.h>
45 #include <epan/etypes.h>
46 #include <epan/greproto.h>
47 #include <epan/ppptypes.h>
48 #include <epan/llcsaps.h>
49 #include <epan/aftypes.h>
50 #include <epan/arcnet_pids.h>
51 #include "packet-ip.h"
52 #include "packet-ipsec.h"
53 #include <epan/in_cksum.h>
54 #include <epan/nlpid.h>
55 #include <epan/tap.h>
56 #include <epan/emem.h>
57 #include <epan/nstime.h>
58
59 static int ip_tap = -1;
60
61 static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
62
63 /* Decode the old IPv4 TOS field as the DiffServ DS Field (RFC2474/2475) */
64 static gboolean g_ip_dscp_actif = TRUE;
65
66 /* Defragment fragmented IP datagrams */
67 static gboolean ip_defragment = TRUE;
68
69 /* Place IP summary in proto tree */
70 static gboolean ip_summary_in_tree = TRUE;
71
72 /* Decode the end of the ICMP payload as ICMP MPLS extensions
73 if the packet in the payload has more than 128 bytes */
74 static gboolean favor_icmp_mpls_ext = FALSE;
75
76 /* Perform IP checksum */
77 static gboolean ip_check_checksum = TRUE;
78
79 static int proto_ip = -1;
80 static int hf_ip_version = -1;
81 static int hf_ip_hdr_len = -1;
82 static int hf_ip_dsfield = -1;
83 static int hf_ip_dsfield_dscp = -1;
84 static int hf_ip_dsfield_ect = -1;
85 static int hf_ip_dsfield_ce = -1;
86 static int hf_ip_tos = -1;
87 static int hf_ip_tos_precedence = -1;
88 static int hf_ip_tos_delay = -1;
89 static int hf_ip_tos_throughput = -1;
90 static int hf_ip_tos_reliability = -1;
91 static int hf_ip_tos_cost = -1;
92 static int hf_ip_len = -1;
93 static int hf_ip_id = -1;
94 static int hf_ip_dst = -1;
95 static int hf_ip_dst_host = -1;
96 static int hf_ip_src = -1;
97 static int hf_ip_src_host = -1;
98 static int hf_ip_addr = -1;
99 static int hf_ip_host = -1;
100 static int hf_ip_flags = -1;
101 static int hf_ip_flags_rf = -1;
102 static int hf_ip_flags_df = -1;
103 static int hf_ip_flags_mf = -1;
104 static int hf_ip_frag_offset = -1;
105 static int hf_ip_ttl = -1;
106 static int hf_ip_proto = -1;
107 static int hf_ip_checksum = -1;
108 static int hf_ip_checksum_good = -1;
109 static int hf_ip_checksum_bad = -1;
110 static int hf_ip_fragments = -1;
111 static int hf_ip_fragment = -1;
112 static int hf_ip_fragment_overlap = -1;
113 static int hf_ip_fragment_overlap_conflict = -1;
114 static int hf_ip_fragment_multiple_tails = -1;
115 static int hf_ip_fragment_too_long_fragment = -1;
116 static int hf_ip_fragment_error = -1;
117 static int hf_ip_reassembled_in = -1;
118
119 static gint ett_ip = -1;
120 static gint ett_ip_dsfield = -1;
121 static gint ett_ip_tos = -1;
122 static gint ett_ip_off = -1;
123 static gint ett_ip_options = -1;
124 static gint ett_ip_option_sec = -1;
125 static gint ett_ip_option_route = -1;
126 static gint ett_ip_option_timestamp = -1;
127 static gint ett_ip_fragments = -1;
128 static gint ett_ip_fragment  = -1;
129 static gint ett_ip_checksum = -1;
130
131 static const fragment_items ip_frag_items = {
132         &ett_ip_fragment,
133         &ett_ip_fragments,
134         &hf_ip_fragments,
135         &hf_ip_fragment,
136         &hf_ip_fragment_overlap,
137         &hf_ip_fragment_overlap_conflict,
138         &hf_ip_fragment_multiple_tails,
139         &hf_ip_fragment_too_long_fragment,
140         &hf_ip_fragment_error,
141         &hf_ip_reassembled_in,
142         "fragments"
143 };
144
145 static dissector_table_t ip_dissector_table;
146
147 static dissector_handle_t ip_handle;
148 static dissector_handle_t ipv6_handle;
149 static dissector_handle_t data_handle;
150
151 static int proto_icmp = -1;
152 static int hf_icmp_type = -1;
153 static int hf_icmp_code = -1;
154 static int hf_icmp_checksum = -1;
155 static int hf_icmp_checksum_bad = -1;
156 static int hf_icmp_ident = -1;
157 static int hf_icmp_seq_num = -1;
158 static int hf_icmp_mtu = -1;
159 static int hf_icmp_redir_gw = -1;
160
161
162 /* Mobile ip */
163 static int hf_icmp_mip_type = -1;
164 static int hf_icmp_mip_length = -1;
165 static int hf_icmp_mip_prefix_length = -1;
166 static int hf_icmp_mip_seq = -1;
167 static int hf_icmp_mip_life = -1;
168 static int hf_icmp_mip_flags = -1;
169 static int hf_icmp_mip_r = -1;
170 static int hf_icmp_mip_b = -1;
171 static int hf_icmp_mip_h = -1;
172 static int hf_icmp_mip_f = -1;
173 static int hf_icmp_mip_m = -1;
174 static int hf_icmp_mip_g = -1;
175 static int hf_icmp_mip_v = -1;
176 static int hf_icmp_mip_rt = -1;
177 static int hf_icmp_mip_reserved = -1;
178 static int hf_icmp_mip_coa = -1;
179 static int hf_icmp_mip_challenge = -1;
180
181 /* MPLS extensions */
182 static int hf_icmp_mpls = -1;
183 static int hf_icmp_mpls_version = -1;
184 static int hf_icmp_mpls_reserved = -1;
185 static int hf_icmp_mpls_checksum = -1;
186 static int hf_icmp_mpls_checksum_bad = -1;
187 static int hf_icmp_mpls_length = -1;
188 static int hf_icmp_mpls_class = -1;
189 static int hf_icmp_mpls_c_type = -1;
190 static int hf_icmp_mpls_label = -1;
191 static int hf_icmp_mpls_exp = -1;
192 static int hf_icmp_mpls_s = -1;
193 static int hf_icmp_mpls_ttl = -1;
194
195 static gint ett_icmp = -1;
196 static gint ett_icmp_mip = -1;
197 static gint ett_icmp_mip_flags = -1;
198 /* MPLS extensions */
199 static gint ett_icmp_mpls = -1;
200 static gint ett_icmp_mpls_object = -1;
201 static gint ett_icmp_mpls_stack_object = -1;
202
203 /* ICMP definitions */
204
205 #define ICMP_ECHOREPLY     0
206 #define ICMP_UNREACH       3
207 #define ICMP_SOURCEQUENCH  4
208 #define ICMP_REDIRECT      5
209 #define ICMP_ECHO          8
210 #define ICMP_RTRADVERT     9
211 #define ICMP_RTRSOLICIT   10
212 #define ICMP_TIMXCEED     11
213 #define ICMP_PARAMPROB    12
214 #define ICMP_TSTAMP       13
215 #define ICMP_TSTAMPREPLY  14
216 #define ICMP_IREQ         15
217 #define ICMP_IREQREPLY    16
218 #define ICMP_MASKREQ      17
219 #define ICMP_MASKREPLY    18
220
221 /* ICMP UNREACHABLE */
222
223 #define ICMP_NET_UNREACH        0       /* Network Unreachable */
224 #define ICMP_HOST_UNREACH       1       /* Host Unreachable */
225 #define ICMP_PROT_UNREACH       2       /* Protocol Unreachable */
226 #define ICMP_PORT_UNREACH       3       /* Port Unreachable */
227 #define ICMP_FRAG_NEEDED        4       /* Fragmentation Needed/DF set */
228 #define ICMP_SR_FAILED          5       /* Source Route failed */
229 #define ICMP_NET_UNKNOWN        6
230 #define ICMP_HOST_UNKNOWN       7
231 #define ICMP_HOST_ISOLATED      8
232 #define ICMP_NET_ANO            9
233 #define ICMP_HOST_ANO           10
234 #define ICMP_NET_UNR_TOS        11
235 #define ICMP_HOST_UNR_TOS       12
236 #define ICMP_PKT_FILTERED       13      /* Packet filtered */
237 #define ICMP_PREC_VIOLATION     14      /* Precedence violation */
238 #define ICMP_PREC_CUTOFF        15      /* Precedence cut off */
239
240
241 /* IP structs and definitions */
242
243 /* Offsets of fields within an IP header. */
244 #define IPH_V_HL        0
245 #define IPH_TOS         1
246 #define IPH_LEN         2
247 #define IPH_ID          4
248 #define IPH_TTL         6
249 #define IPH_OFF         8
250 #define IPH_P           9
251 #define IPH_SUM         10
252 #define IPH_SRC         12
253 #define IPH_DST         16
254
255 /* Minimum IP header length. */
256 #define IPH_MIN_LEN     20
257
258 /* IP flags. */
259 #define IP_RF           0x8000          /* Flag: "Reserved bit"         */
260 #define IP_DF           0x4000          /* Flag: "Don't Fragment"       */
261 #define IP_MF           0x2000          /* Flag: "More Fragments"       */
262 #define IP_OFFSET       0x1FFF          /* "Fragment Offset" part       */
263
264 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
265 #define IPDSFIELD_DSCP_MASK     0xFC
266 #define IPDSFIELD_ECN_MASK     0x03
267 #define IPDSFIELD_DSCP_SHIFT    2
268 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
269 #define IPDSFIELD_ECN(dsfield)  ((dsfield)&IPDSFIELD_ECN_MASK)
270 #define IPDSFIELD_DSCP_DEFAULT  0x00
271 #define IPDSFIELD_DSCP_CS1      0x08
272 #define IPDSFIELD_DSCP_CS2      0x10
273 #define IPDSFIELD_DSCP_CS3      0x18
274 #define IPDSFIELD_DSCP_CS4      0x20
275 #define IPDSFIELD_DSCP_CS5      0x28
276 #define IPDSFIELD_DSCP_CS6      0x30
277 #define IPDSFIELD_DSCP_CS7      0x38
278 #define IPDSFIELD_DSCP_AF11     0x0A
279 #define IPDSFIELD_DSCP_AF12     0x0C
280 #define IPDSFIELD_DSCP_AF13     0x0E
281 #define IPDSFIELD_DSCP_AF21     0x12
282 #define IPDSFIELD_DSCP_AF22     0x14
283 #define IPDSFIELD_DSCP_AF23     0x16
284 #define IPDSFIELD_DSCP_AF31     0x1A
285 #define IPDSFIELD_DSCP_AF32     0x1C
286 #define IPDSFIELD_DSCP_AF33     0x1E
287 #define IPDSFIELD_DSCP_AF41     0x22
288 #define IPDSFIELD_DSCP_AF42     0x24
289 #define IPDSFIELD_DSCP_AF43     0x26
290 #define IPDSFIELD_DSCP_EF       0x2E
291 #define IPDSFIELD_ECT_MASK      0x02
292 #define IPDSFIELD_CE_MASK       0x01
293
294 /* IP TOS, superseded by the DS Field, RFC 2474. */
295 #define IPTOS_TOS_MASK    0x1E
296 #define IPTOS_TOS(tos)    ((tos) & IPTOS_TOS_MASK)
297 #define IPTOS_NONE        0x00
298 #define IPTOS_LOWCOST     0x02
299 #define IPTOS_RELIABILITY 0x04
300 #define IPTOS_THROUGHPUT  0x08
301 #define IPTOS_LOWDELAY    0x10
302 #define IPTOS_SECURITY    0x1E
303
304 #define IPTOS_PREC_MASK         0xE0
305 #define IPTOS_PREC_SHIFT        5
306 #define IPTOS_PREC(tos)         (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
307 #define IPTOS_PREC_NETCONTROL           7
308 #define IPTOS_PREC_INTERNETCONTROL      6
309 #define IPTOS_PREC_CRITIC_ECP           5
310 #define IPTOS_PREC_FLASHOVERRIDE        4
311 #define IPTOS_PREC_FLASH                3
312 #define IPTOS_PREC_IMMEDIATE            2
313 #define IPTOS_PREC_PRIORITY             1
314 #define IPTOS_PREC_ROUTINE              0
315
316 /* IP options */
317 #define IPOPT_COPY              0x80
318
319 #define IPOPT_CONTROL           0x00
320 #define IPOPT_RESERVED1         0x20
321 #define IPOPT_MEASUREMENT       0x40
322 #define IPOPT_RESERVED2         0x60
323
324 #define IPOPT_END       (0 |IPOPT_CONTROL)
325 #define IPOPT_NOOP      (1 |IPOPT_CONTROL)
326 #define IPOPT_SEC       (2 |IPOPT_CONTROL|IPOPT_COPY)
327 #define IPOPT_LSRR      (3 |IPOPT_CONTROL|IPOPT_COPY)
328 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
329 #define IPOPT_RR        (7 |IPOPT_CONTROL)
330 #define IPOPT_SID       (8 |IPOPT_CONTROL|IPOPT_COPY)
331 #define IPOPT_SSRR      (9 |IPOPT_CONTROL|IPOPT_COPY)
332 #define IPOPT_RA        (20|IPOPT_CONTROL|IPOPT_COPY)
333
334 /* IP option lengths */
335 #define IPOLEN_SEC      11
336 #define IPOLEN_LSRR_MIN 3
337 #define IPOLEN_TIMESTAMP_MIN 5
338 #define IPOLEN_RR_MIN   3
339 #define IPOLEN_SID      4
340 #define IPOLEN_SSRR_MIN 3
341 #define IPOLEN_RA       4
342
343 #define IPSEC_UNCLASSIFIED      0x0000
344 #define IPSEC_CONFIDENTIAL      0xF135
345 #define IPSEC_EFTO              0x789A
346 #define IPSEC_MMMM              0xBC4D
347 #define IPSEC_RESTRICTED        0xAF13
348 #define IPSEC_SECRET            0xD788
349 #define IPSEC_TOPSECRET         0x6BC5
350 #define IPSEC_RESERVED1         0x35E2
351 #define IPSEC_RESERVED2         0x9AF1
352 #define IPSEC_RESERVED3         0x4D78
353 #define IPSEC_RESERVED4         0x24BD
354 #define IPSEC_RESERVED5         0x135E
355 #define IPSEC_RESERVED6         0x89AF
356 #define IPSEC_RESERVED7         0xC4D6
357 #define IPSEC_RESERVED8         0xE26B
358
359 #define IPOPT_TS_TSONLY         0               /* timestamps only */
360 #define IPOPT_TS_TSANDADDR      1               /* timestamps and addresses */
361 #define IPOPT_TS_PRESPEC        3               /* specified modules only */
362
363 /*
364  * defragmentation of IPv4
365  */
366 static GHashTable *ip_fragment_table = NULL;
367 static GHashTable *ip_reassembled_table = NULL;
368
369 static void
370 ip_defragment_init(void)
371 {
372   fragment_table_init(&ip_fragment_table);
373   reassembled_table_init(&ip_reassembled_table);
374 }
375
376 void
377 capture_ip(const guchar *pd, int offset, int len, packet_counts *ld) {
378   if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
379     ld->other++;
380     return;
381   }
382   switch (pd[offset + 9]) {
383     case IP_PROTO_TCP:
384       ld->tcp++;
385       break;
386     case IP_PROTO_UDP:
387     case IP_PROTO_UDPLITE:
388       ld->udp++;
389       break;
390     case IP_PROTO_ICMP:
391     case IP_PROTO_ICMPV6:       /* XXX - separate counters? */
392       ld->icmp++;
393       break;
394     case IP_PROTO_SCTP:
395       ld->sctp++;
396       break;
397     case IP_PROTO_OSPF:
398       ld->ospf++;
399       break;
400     case IP_PROTO_GRE:
401       ld->gre++;
402       break;
403     case IP_PROTO_VINES:
404       ld->vines++;
405       break;
406     default:
407       ld->other++;
408   }
409 }
410
411 static void
412 dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
413                         guint optlen, packet_info *pinfo _U_,
414                         proto_tree *opt_tree)
415 {
416   proto_tree *field_tree = NULL;
417   proto_item *tf;
418   guint      val;
419   static const value_string secl_vals[] = {
420     {IPSEC_UNCLASSIFIED, "Unclassified"},
421     {IPSEC_CONFIDENTIAL, "Confidential"},
422     {IPSEC_EFTO,         "EFTO"        },
423     {IPSEC_MMMM,         "MMMM"        },
424     {IPSEC_RESTRICTED,   "Restricted"  },
425     {IPSEC_SECRET,       "Secret"      },
426     {IPSEC_TOPSECRET,    "Top secret"  },
427     {IPSEC_RESERVED1,    "Reserved"    },
428     {IPSEC_RESERVED2,    "Reserved"    },
429     {IPSEC_RESERVED3,    "Reserved"    },
430     {IPSEC_RESERVED4,    "Reserved"    },
431     {IPSEC_RESERVED5,    "Reserved"    },
432     {IPSEC_RESERVED6,    "Reserved"    },
433     {IPSEC_RESERVED7,    "Reserved"    },
434     {IPSEC_RESERVED8,    "Reserved"    },
435     {0,                  NULL          } };
436
437   tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s:", optp->name);
438   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
439   offset += 2;
440
441   val = tvb_get_ntohs(tvb, offset);
442   proto_tree_add_text(field_tree, tvb, offset,       2,
443               "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
444   offset += 2;
445
446   val = tvb_get_ntohs(tvb, offset);
447   proto_tree_add_text(field_tree, tvb, offset,         2,
448               "Compartments: %u", val);
449   offset += 2;
450
451   proto_tree_add_text(field_tree, tvb, offset,         2,
452               "Handling restrictions: %c%c",
453               tvb_get_guint8(tvb, offset),
454               tvb_get_guint8(tvb, offset + 1));
455   offset += 2;
456
457   proto_tree_add_text(field_tree, tvb, offset,         3,
458               "Transmission control code: %c%c%c",
459               tvb_get_guint8(tvb, offset),
460               tvb_get_guint8(tvb, offset + 1),
461               tvb_get_guint8(tvb, offset + 2));
462 }
463
464 static void
465 dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
466                         guint optlen, packet_info *pinfo _U_,
467                         proto_tree *opt_tree)
468 {
469   proto_tree *field_tree = NULL;
470   proto_item *tf;
471   int ptr;
472   int optoffset = 0;
473   guint32 addr;
474
475   tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s (%u bytes)",
476                                 optp->name, optlen);
477   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
478
479   optoffset += 2;       /* skip past type and length */
480   optlen -= 2;          /* subtract size of type and length */
481
482   ptr = tvb_get_guint8(tvb, offset + optoffset);
483   proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
484               "Pointer: %d%s", ptr,
485               ((ptr < 4) ? " (points before first address)" :
486                ((ptr & 3) ? " (points to middle of address)" : "")));
487   optoffset++;
488   optlen--;
489   ptr--;        /* ptr is 1-origin */
490
491   while (optlen > 0) {
492     if (optlen < 4) {
493       proto_tree_add_text(field_tree, tvb, offset,      optlen,
494         "(suboption would go past end of option)");
495       break;
496     }
497
498     addr = tvb_get_ipv4(tvb, offset + optoffset);
499     proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
500               "%s%s",
501               ((addr == 0) ? "-" : (char *)get_hostname(addr)),
502               ((optoffset == ptr) ? " <- (current)" : ""));
503     optoffset += 4;
504     optlen -= 4;
505   }
506 }
507
508 static void
509 dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
510                         guint optlen, packet_info *pinfo _U_,
511                         proto_tree *opt_tree)
512 {
513   proto_tree_add_text(opt_tree, tvb, offset,      optlen,
514     "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
515   return;
516 }
517
518 static void
519 dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
520     int offset, guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
521 {
522   proto_tree *field_tree = NULL;
523   proto_item *tf;
524   int        ptr;
525   int        optoffset = 0;
526   int        flg;
527   static const value_string flag_vals[] = {
528     {IPOPT_TS_TSONLY,    "Time stamps only"                      },
529     {IPOPT_TS_TSANDADDR, "Time stamp and address"                },
530     {IPOPT_TS_PRESPEC,   "Time stamps for prespecified addresses"},
531     {0,                  NULL                                    } };
532   guint32 addr;
533   guint ts;
534
535   tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s:", optp->name);
536   field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
537
538   optoffset += 2;       /* skip past type and length */
539   optlen -= 2;          /* subtract size of type and length */
540
541   ptr = tvb_get_guint8(tvb, offset + optoffset);
542   proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
543               "Pointer: %d%s", ptr,
544               ((ptr < 5) ? " (points before first address)" :
545                (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
546   optoffset++;
547   optlen--;
548   ptr--;        /* ptr is 1-origin */
549
550   flg = tvb_get_guint8(tvb, offset + optoffset);
551   proto_tree_add_text(field_tree, tvb, offset + optoffset,   1,
552         "Overflow: %u", flg >> 4);
553   flg &= 0xF;
554   proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
555         "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
556   optoffset++;
557   optlen--;
558
559   while (optlen > 0) {
560     if (flg == IPOPT_TS_TSANDADDR) {
561       if (optlen < 8) {
562         proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
563           "(suboption would go past end of option)");
564         break;
565       }
566       addr = tvb_get_ipv4(tvb, offset + optoffset);
567       ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
568       optlen -= 8;
569       proto_tree_add_text(field_tree, tvb, offset + optoffset,      8,
570           "Address = %s, time stamp = %u",
571           ((addr == 0) ? "-" :  (char *)get_hostname(addr)),
572           ts);
573       optoffset += 8;
574     } else {
575       if (optlen < 4) {
576         proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
577           "(suboption would go past end of option)");
578         break;
579       }
580       ts = tvb_get_ntohl(tvb, offset + optoffset);
581       optlen -= 4;
582       proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
583           "Time stamp = %u", ts);
584       optoffset += 4;
585     }
586   }
587 }
588
589 static void
590 dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
591                 guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
592 {
593   /* Router-Alert, as defined by RFC2113 */
594   int opt = tvb_get_ntohs(tvb, offset + 2);
595   static const value_string ra_opts[] = {
596         {0, "Every router examines packet"},
597         {0, NULL}
598   };
599
600   proto_tree_add_text(opt_tree, tvb, offset,      optlen,
601     "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
602   return;
603 }
604
605 static const ip_tcp_opt ipopts[] = {
606   {
607     IPOPT_END,
608     "EOL",
609     NULL,
610     NO_LENGTH,
611     0,
612     NULL,
613   },
614   {
615     IPOPT_NOOP,
616     "NOP",
617     NULL,
618     NO_LENGTH,
619     0,
620     NULL,
621   },
622   {
623     IPOPT_SEC,
624     "Security",
625     &ett_ip_option_sec,
626     FIXED_LENGTH,
627     IPOLEN_SEC,
628     dissect_ipopt_security
629   },
630   {
631     IPOPT_SSRR,
632     "Strict source route",
633     &ett_ip_option_route,
634     VARIABLE_LENGTH,
635     IPOLEN_SSRR_MIN,
636     dissect_ipopt_route
637   },
638   {
639     IPOPT_LSRR,
640     "Loose source route",
641     &ett_ip_option_route,
642     VARIABLE_LENGTH,
643     IPOLEN_LSRR_MIN,
644     dissect_ipopt_route
645   },
646   {
647     IPOPT_RR,
648     "Record route",
649     &ett_ip_option_route,
650     VARIABLE_LENGTH,
651     IPOLEN_RR_MIN,
652     dissect_ipopt_route
653   },
654   {
655     IPOPT_SID,
656     "Stream identifier",
657     NULL,
658     FIXED_LENGTH,
659     IPOLEN_SID,
660     dissect_ipopt_sid
661   },
662   {
663     IPOPT_TIMESTAMP,
664     "Time stamp",
665     &ett_ip_option_timestamp,
666     VARIABLE_LENGTH,
667     IPOLEN_TIMESTAMP_MIN,
668     dissect_ipopt_timestamp
669   },
670   {
671     IPOPT_RA,
672     "Router Alert",
673     NULL,
674     FIXED_LENGTH,
675     IPOLEN_RA,
676     dissect_ipopt_ra
677   },
678 };
679
680 #define N_IP_OPTS       (sizeof ipopts / sizeof ipopts[0])
681
682 /* Dissect the IP or TCP options in a packet. */
683 void
684 dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
685                         const ip_tcp_opt *opttab, int nopts, int eol,
686                         packet_info *pinfo, proto_tree *opt_tree)
687 {
688   guchar            opt;
689   const ip_tcp_opt *optp;
690   opt_len_type      len_type;
691   unsigned int      optlen;
692   const char       *name;
693 #define NAME_STR_LEN 7+1+1+2+2+1+1      /* "Unknown (0x%02x)" */
694   char             *name_str;
695   void            (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
696                                 int, guint, packet_info *, proto_tree *);
697   guint             len;
698
699   name_str=ep_alloc(NAME_STR_LEN);
700   while (length > 0) {
701     opt = tvb_get_guint8(tvb, offset);
702     for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
703       if (optp->optcode == opt)
704         break;
705     }
706     if (optp == &opttab[nopts]) {
707       /* We assume that the only NO_LENGTH options are EOL and NOP options,
708          so that we can treat unknown options as VARIABLE_LENGTH with a
709          minimum of 2, and at least be able to move on to the next option
710          by using the length in the option. */
711       optp = NULL;      /* indicate that we don't know this option */
712       len_type = VARIABLE_LENGTH;
713       optlen = 2;
714       g_snprintf(name_str, NAME_STR_LEN, "Unknown (0x%02x)", opt);
715       name = name_str;
716       dissect = NULL;
717     } else {
718       len_type = optp->len_type;
719       optlen = optp->optlen;
720       name = optp->name;
721       dissect = optp->dissect;
722     }
723     --length;      /* account for type byte */
724     if (len_type != NO_LENGTH) {
725       /* Option has a length. Is it in the packet? */
726       if (length == 0) {
727         /* Bogus - packet must at least include option code byte and
728            length byte! */
729         proto_tree_add_text(opt_tree, tvb, offset,      1,
730               "%s (length byte past end of options)", name);
731         return;
732       }
733       len = tvb_get_guint8(tvb, offset + 1);  /* total including type, len */
734       --length;    /* account for length byte */
735       if (len < 2) {
736         /* Bogus - option length is too short to include option code and
737            option length. */
738         proto_tree_add_text(opt_tree, tvb, offset,      2,
739               "%s (with too-short option length = %u byte%s)", name,
740               len, plurality(len, "", "s"));
741         return;
742       } else if (len - 2 > length) {
743         /* Bogus - option goes past the end of the header. */
744         proto_tree_add_text(opt_tree, tvb, offset,      length,
745               "%s (option length = %u byte%s says option goes past end of options)",
746               name, len, plurality(len, "", "s"));
747         return;
748       } else if (len_type == FIXED_LENGTH && len != optlen) {
749         /* Bogus - option length isn't what it's supposed to be for this
750            option. */
751         proto_tree_add_text(opt_tree, tvb, offset,      len,
752               "%s (with option length = %u byte%s; should be %u)", name,
753               len, plurality(len, "", "s"), optlen);
754         return;
755       } else if (len_type == VARIABLE_LENGTH && len < optlen) {
756         /* Bogus - option length is less than what it's supposed to be for
757            this option. */
758         proto_tree_add_text(opt_tree, tvb, offset,      len,
759               "%s (with option length = %u byte%s; should be >= %u)", name,
760               len, plurality(len, "", "s"), optlen);
761         return;
762       } else {
763         if (optp == NULL) {
764           proto_tree_add_text(opt_tree, tvb, offset,    len, "%s (%u byte%s)",
765                                 name, len, plurality(len, "", "s"));
766         } else {
767           if (dissect != NULL) {
768             /* Option has a dissector. */
769             (*dissect)(optp, tvb, offset,          len, pinfo, opt_tree);
770           } else {
771             /* Option has no data, hence no dissector. */
772             proto_tree_add_text(opt_tree, tvb, offset,  len, "%s", name);
773           }
774         }
775         len -= 2;       /* subtract size of type and length */
776         offset += 2 + len;
777       }
778       length -= len;
779     } else {
780       proto_tree_add_text(opt_tree, tvb, offset,      1, "%s", name);
781       offset += 1;
782     }
783     if (opt == eol)
784       break;
785   }
786 }
787
788 const value_string dscp_vals[] = {
789                   { IPDSFIELD_DSCP_DEFAULT, "Default"               },
790                   { IPDSFIELD_DSCP_CS1,     "Class Selector 1"      },
791                   { IPDSFIELD_DSCP_CS2,     "Class Selector 2"      },
792                   { IPDSFIELD_DSCP_CS3,     "Class Selector 3"      },
793                   { IPDSFIELD_DSCP_CS4,     "Class Selector 4"      },
794                   { IPDSFIELD_DSCP_CS5,     "Class Selector 5"      },
795                   { IPDSFIELD_DSCP_CS6,     "Class Selector 6"      },
796                   { IPDSFIELD_DSCP_CS7,     "Class Selector 7"      },
797                   { IPDSFIELD_DSCP_AF11,    "Assured Forwarding 11" },
798                   { IPDSFIELD_DSCP_AF12,    "Assured Forwarding 12" },
799                   { IPDSFIELD_DSCP_AF13,    "Assured Forwarding 13" },
800                   { IPDSFIELD_DSCP_AF21,    "Assured Forwarding 21" },
801                   { IPDSFIELD_DSCP_AF22,    "Assured Forwarding 22" },
802                   { IPDSFIELD_DSCP_AF23,    "Assured Forwarding 23" },
803                   { IPDSFIELD_DSCP_AF31,    "Assured Forwarding 31" },
804                   { IPDSFIELD_DSCP_AF32,    "Assured Forwarding 32" },
805                   { IPDSFIELD_DSCP_AF33,    "Assured Forwarding 33" },
806                   { IPDSFIELD_DSCP_AF41,    "Assured Forwarding 41" },
807                   { IPDSFIELD_DSCP_AF42,    "Assured Forwarding 42" },
808                   { IPDSFIELD_DSCP_AF43,    "Assured Forwarding 43" },
809                   { IPDSFIELD_DSCP_EF,      "Expedited Forwarding"  },
810                   { 0,                      NULL                    } };
811
812 static const value_string precedence_vals[] = {
813                   { IPTOS_PREC_ROUTINE,         "routine"              },
814                   { IPTOS_PREC_PRIORITY,        "priority"             },
815                   { IPTOS_PREC_IMMEDIATE,       "immediate"            },
816                   { IPTOS_PREC_FLASH,           "flash"                },
817                   { IPTOS_PREC_FLASHOVERRIDE,   "flash override"       },
818                   { IPTOS_PREC_CRITIC_ECP,      "CRITIC/ECP"           },
819                   { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
820                   { IPTOS_PREC_NETCONTROL,      "network control"      },
821                   { 0,                          NULL                   } };
822
823 static const value_string iptos_vals[] = {
824         { IPTOS_NONE,           "None" },
825         { IPTOS_LOWCOST,        "Minimize cost" },
826         { IPTOS_RELIABILITY,    "Maximize reliability" },
827         { IPTOS_THROUGHPUT,     "Maximize throughput" },
828         { IPTOS_LOWDELAY,       "Minimize delay" },
829         { IPTOS_SECURITY,       "Maximize security" },
830         { 0,                    NULL }
831 };
832
833 static const true_false_string tos_set_low = {
834   "Low",
835   "Normal"
836 };
837
838 static const true_false_string tos_set_high = {
839   "High",
840   "Normal"
841 };
842
843 static guint16 ip_checksum(const guint8 *ptr, int len)
844 {
845         vec_t cksum_vec[1];
846
847         cksum_vec[0].ptr = ptr;
848         cksum_vec[0].len = len;
849         return in_cksum(&cksum_vec[0], 1);
850 }
851
852 static void
853 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
854 {
855   proto_tree *ip_tree = NULL, *field_tree;
856   proto_item *ti = NULL, *tf;
857   guint32    addr;
858   int        offset = 0;
859   guint      hlen, optlen;
860   guint16    flags;
861   guint8     nxt;
862   guint16    ipsum;
863   fragment_data *ipfd_head=NULL;
864   tvbuff_t   *next_tvb;
865   gboolean   update_col_info = TRUE;
866   gboolean   save_fragmented;
867   static e_ip eip_arr[4];
868   static int eip_current=0;
869   e_ip *iph;
870   const guchar          *src_addr, *dst_addr;
871   guint32               src32, dst32;
872   proto_tree *tree;
873   proto_item *item;
874   proto_tree *checksum_tree;
875
876   tree=parent_tree;
877
878   eip_current++;
879   if(eip_current==4){
880      eip_current=0;
881   }
882   iph=&eip_arr[eip_current];
883
884   if (check_col(pinfo->cinfo, COL_PROTOCOL))
885     col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
886   if (check_col(pinfo->cinfo, COL_INFO))
887     col_clear(pinfo->cinfo, COL_INFO);
888
889   iph->ip_v_hl = tvb_get_guint8(tvb, offset);
890   if ( hi_nibble(iph->ip_v_hl) == 6){
891           call_dissector(ipv6_handle, tvb, pinfo, parent_tree);
892           return;
893   }
894
895   hlen = lo_nibble(iph->ip_v_hl) * 4;   /* IP header length, in bytes */
896
897   if (tree) {
898     ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
899     ip_tree = proto_item_add_subtree(ti, ett_ip);
900
901     proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1,
902         hi_nibble(iph->ip_v_hl));
903   }
904
905   /* if IP is not referenced from any filters we dont need to worry about
906      generating any tree items.  We must do this after we created the actual
907      protocol above so that proto hier stat still works though.
908   */
909   if(!proto_field_is_referenced(parent_tree, proto_ip)){
910     tree=NULL;
911   }
912
913   if (hlen < IPH_MIN_LEN) {
914     if (check_col(pinfo->cinfo, COL_INFO))
915       col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
916        hlen, IPH_MIN_LEN);
917     if (tree) {
918       proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
919         "Header length: %u bytes (bogus, must be at least %u)", hlen,
920         IPH_MIN_LEN);
921     }
922     goto end_of_ip;
923   }
924
925   if (tree) {
926         proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
927         "Header length: %u bytes", hlen);
928   }
929
930   iph->ip_tos = tvb_get_guint8(tvb, offset + 1);
931   if (tree) {
932     if (g_ip_dscp_actif) {
933       tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph->ip_tos,
934            "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph->ip_tos,
935            IPDSFIELD_DSCP(iph->ip_tos), val_to_str(IPDSFIELD_DSCP(iph->ip_tos), dscp_vals,
936            "Unknown DSCP"),IPDSFIELD_ECN(iph->ip_tos));
937
938       field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
939       proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph->ip_tos);
940       proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph->ip_tos);
941       proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph->ip_tos);
942     } else {
943       tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph->ip_tos,
944           "Type of service: 0x%02x (%s)", iph->ip_tos,
945           val_to_str( IPTOS_TOS(iph->ip_tos), iptos_vals, "Unknown") );
946
947       field_tree = proto_item_add_subtree(tf, ett_ip_tos);
948       proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph->ip_tos);
949       proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph->ip_tos);
950       proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph->ip_tos);
951       proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph->ip_tos);
952       proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph->ip_tos);
953     }
954   }
955
956   /* Length of IP datagram.
957      XXX - what if this is greater than the reported length of the
958      tvbuff?  This could happen, for example, in an IP datagram
959      inside an ICMP datagram; we need to somehow let the
960      dissector we call know that, as it might want to avoid
961      doing its checksumming. */
962   iph->ip_len = tvb_get_ntohs(tvb, offset + 2);
963
964   /* Adjust the length of this tvbuff to include only the IP datagram. */
965   set_actual_length(tvb, iph->ip_len);
966
967   if (iph->ip_len < hlen) {
968     if (check_col(pinfo->cinfo, COL_INFO))
969       col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP length (%u, less than header length %u)",
970        iph->ip_len, hlen);
971     if (tree) {
972       proto_tree_add_uint_format(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len,
973        "Total length: %u bytes (bogus, less than header length %u)", iph->ip_len,
974        hlen);
975     }
976     goto end_of_ip;
977   }
978   if (tree)
979         proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len);
980
981   iph->ip_id  = tvb_get_ntohs(tvb, offset + 4);
982   if (tree)
983         proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph->ip_id);
984
985   iph->ip_off = tvb_get_ntohs(tvb, offset + 6);
986   if (tree) {
987     flags = (iph->ip_off & (IP_RF | IP_DF | IP_MF)) >> 12;
988     tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
989     field_tree = proto_item_add_subtree(tf, ett_ip_off);
990     proto_tree_add_boolean(field_tree, hf_ip_flags_rf, tvb, offset + 6, 1, flags);
991     if (flags & (IP_DF>>12)) proto_item_append_text(tf, " (Don't Fragment)");
992     proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags);
993     if (flags & (IP_MF>>12)) proto_item_append_text(tf, " (More Fragments)");
994     proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags);
995
996     proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
997       (iph->ip_off & IP_OFFSET)*8);
998   }
999
1000   if (tree)
1001     proto_tree_add_item(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, FALSE);
1002
1003   iph->ip_p = tvb_get_guint8(tvb, offset + 9);
1004   if (tree) {
1005     proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph->ip_p,
1006         "Protocol: %s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
1007   }
1008
1009   iph->ip_sum = tvb_get_ntohs(tvb, offset + 10);
1010
1011   /*
1012    * If we have the entire IP header available, check the checksum.
1013    */
1014   if (ip_check_checksum && tvb_bytes_exist(tvb, offset, hlen)) {
1015     ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
1016   if (tree) {
1017                 if (ipsum == 0) {
1018                         item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
1019                                           "Header checksum: 0x%04x [correct]", iph->ip_sum);
1020                         checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
1021                         item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, TRUE);
1022                         PROTO_ITEM_SET_GENERATED(item);
1023                         item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, FALSE);
1024                         PROTO_ITEM_SET_GENERATED(item);
1025                 } else {
1026                         item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
1027                                   "Header checksum: 0x%04x [incorrect, should be 0x%04x]", iph->ip_sum,
1028                         in_cksum_shouldbe(iph->ip_sum, ipsum));
1029                         checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
1030                         item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, FALSE);
1031                         PROTO_ITEM_SET_GENERATED(item);
1032                         item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
1033                         PROTO_ITEM_SET_GENERATED(item);
1034                 }
1035     }
1036         } else {
1037     ipsum = 0;
1038     if (tree) {
1039                 item = proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
1040                         "Header checksum: 0x%04x [%s]", iph->ip_sum,
1041                         ip_check_checksum ? "not all data available" : "validation disabled");
1042                 checksum_tree = proto_item_add_subtree(item, ett_ip_checksum);
1043                 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_good, tvb, offset + 10, 2, FALSE);
1044                 PROTO_ITEM_SET_GENERATED(item);
1045                 item = proto_tree_add_boolean(checksum_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, FALSE);
1046                 PROTO_ITEM_SET_GENERATED(item);
1047         }
1048   }
1049   src_addr = tvb_get_ptr(tvb, offset + IPH_SRC, 4);
1050   src32 = tvb_get_ntohl(tvb, offset + IPH_SRC);
1051   SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, src_addr);
1052   SET_ADDRESS(&pinfo->src, AT_IPv4, 4, src_addr);
1053   SET_ADDRESS(&iph->ip_src, AT_IPv4, 4, src_addr);
1054   if (tree) {
1055     memcpy(&addr, iph->ip_src.data, 4);
1056     if (ip_summary_in_tree) {
1057       proto_item_append_text(ti, ", Src: %s (%s)",
1058                 get_hostname(addr), ip_to_str(iph->ip_src.data));
1059     }
1060     proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, addr);
1061     item = proto_tree_add_ipv4(ip_tree, hf_ip_addr, tvb, offset + 12, 4, addr);
1062     PROTO_ITEM_SET_HIDDEN(item);
1063     item = proto_tree_add_string(ip_tree, hf_ip_src_host, tvb, offset + 12, 4, get_hostname(addr));
1064     PROTO_ITEM_SET_GENERATED(item);
1065     PROTO_ITEM_SET_HIDDEN(item);
1066     item = proto_tree_add_string(ip_tree, hf_ip_host, tvb, offset + 12, 4, get_hostname(addr));
1067     PROTO_ITEM_SET_GENERATED(item);
1068     PROTO_ITEM_SET_HIDDEN(item);
1069   }
1070   dst_addr = tvb_get_ptr(tvb, offset + IPH_DST, 4);
1071   dst32 = tvb_get_ntohl(tvb, offset + IPH_DST);
1072   SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, dst_addr);
1073   SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, dst_addr);
1074   SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, dst_addr);
1075
1076   if (tree) {
1077     memcpy(&addr, iph->ip_dst.data, 4);
1078     if (ip_summary_in_tree) {
1079       proto_item_append_text(ti, ", Dst: %s (%s)",
1080                 get_hostname(addr), ip_to_str(iph->ip_dst.data));
1081     }
1082     proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, addr);
1083     item = proto_tree_add_ipv4(ip_tree, hf_ip_addr, tvb, offset + 16, 4, addr);
1084     PROTO_ITEM_SET_HIDDEN(item);
1085     item = proto_tree_add_string(ip_tree, hf_ip_dst_host, tvb, offset + 16, 4, get_hostname(addr));
1086     PROTO_ITEM_SET_GENERATED(item);
1087     PROTO_ITEM_SET_HIDDEN(item);
1088     item = proto_tree_add_string(ip_tree, hf_ip_host, tvb, offset + 16, 4, get_hostname(addr));
1089     PROTO_ITEM_SET_GENERATED(item);
1090     PROTO_ITEM_SET_HIDDEN(item);
1091   }
1092
1093   if (tree) {
1094     /* Decode IP options, if any. */
1095     if (hlen > IPH_MIN_LEN) {
1096       /* There's more than just the fixed-length header.  Decode the
1097          options. */
1098       optlen = hlen - IPH_MIN_LEN;      /* length of options, in bytes */
1099       tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
1100         "Options: (%u bytes)", optlen);
1101       field_tree = proto_item_add_subtree(tf, ett_ip_options);
1102       dissect_ip_tcp_options(tvb, offset + 20, optlen,
1103          ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
1104     }
1105   }
1106
1107   pinfo->ipproto = iph->ip_p;
1108
1109   pinfo->iplen = iph->ip_len;
1110
1111   pinfo->iphdrlen = hlen;
1112
1113   /* Skip over header + options */
1114   offset += hlen;
1115   nxt = iph->ip_p;      /* XXX - what if this isn't the same for all fragments? */
1116
1117   /* If ip_defragment is on, this is a fragment, we have all the data
1118    * in the fragment, and the header checksum is valid, then just add
1119    * the fragment to the hashtable.
1120    */
1121   save_fragmented = pinfo->fragmented;
1122   if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
1123       tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
1124       ipsum == 0) {
1125                 ipfd_head = fragment_add_check(tvb, offset, pinfo, 
1126                              iph->ip_p ^ iph->ip_id ^ src32 ^ dst32,
1127                              ip_fragment_table,
1128                              ip_reassembled_table,
1129                              (iph->ip_off & IP_OFFSET)*8,
1130                              pinfo->iplen - pinfo->iphdrlen,
1131                              iph->ip_off & IP_MF);
1132
1133     next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv4",
1134       ipfd_head, &ip_frag_items, &update_col_info, ip_tree);
1135   } else {
1136     /* If this is the first fragment, dissect its contents, otherwise
1137        just show it as a fragment.
1138
1139        XXX - if we eventually don't save the reassembled contents of all
1140        fragmented datagrams, we may want to always reassemble. */
1141     if (iph->ip_off & IP_OFFSET) {
1142       /* Not the first fragment - don't dissect it. */
1143       next_tvb = NULL;
1144     } else {
1145       /* First fragment, or not fragmented.  Dissect what we have here. */
1146
1147       /* Get a tvbuff for the payload. */
1148       next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1149
1150       /*
1151        * If this is the first fragment, but not the only fragment,
1152        * tell the next protocol that.
1153        */
1154       if (iph->ip_off & IP_MF)
1155         pinfo->fragmented = TRUE;
1156       else
1157         pinfo->fragmented = FALSE;
1158     }
1159   }
1160
1161   if (next_tvb == NULL) {
1162     /* Just show this as a fragment. */
1163     if (check_col(pinfo->cinfo, COL_INFO)) {
1164       col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1165         ipprotostr(iph->ip_p), iph->ip_p, (iph->ip_off & IP_OFFSET) * 8);
1166     }
1167     if( ipfd_head && ipfd_head->reassembled_in != pinfo->fd->num ){
1168       if (check_col(pinfo->cinfo, COL_INFO)) {
1169         col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]",
1170           ipfd_head->reassembled_in);
1171       }
1172     }
1173
1174     call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
1175                    parent_tree);
1176     pinfo->fragmented = save_fragmented;
1177     goto end_of_ip;
1178   }
1179
1180   /* Hand off to the next protocol.
1181
1182      XXX - setting the columns only after trying various dissectors means
1183      that if one of those dissectors throws an exception, the frame won't
1184      even be labelled as an IP frame; ideally, if a frame being dissected
1185      throws an exception, it'll be labelled as a mangled frame of the
1186      type in question. */
1187   if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, parent_tree)) {
1188     /* Unknown protocol */
1189     if (update_col_info) {
1190       if (check_col(pinfo->cinfo, COL_INFO))
1191         col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
1192     }
1193     call_dissector(data_handle,next_tvb, pinfo, parent_tree);
1194   }
1195   pinfo->fragmented = save_fragmented;
1196
1197 end_of_ip:
1198   tap_queue_packet(ip_tap, pinfo, iph);
1199
1200 }
1201
1202 #define ICMP_MIP_EXTENSION_PAD  0
1203 #define ICMP_MIP_MOB_AGENT_ADV  16
1204 #define ICMP_MIP_PREFIX_LENGTHS 19
1205 #define ICMP_MIP_CHALLENGE      24
1206
1207 static value_string mip_extensions[] = {
1208   { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"},  /* RFC 2002 */
1209   { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1210                                                             /* RFC 2002 */
1211   { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"},   /* RFC 2002 */
1212   { ICMP_MIP_CHALLENGE, "Challenge Extension"},             /* RFC 3012 */
1213   { 0, NULL}
1214 };
1215
1216 /*
1217  * Dissect the mobile ip advertisement extensions.
1218  */
1219 static void
1220 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1221 {
1222   guint8       type;
1223   guint8       length;
1224   guint8       flags;
1225   proto_item   *ti;
1226   proto_tree   *mip_tree=NULL;
1227   proto_tree   *flags_tree=NULL;
1228   gint         numCOAs;
1229   gint         i;
1230
1231   /* Not much to do if we're not parsing everything */
1232   if (!tree) return;
1233
1234   while (tvb_reported_length_remaining(tvb, offset) > 0) {
1235
1236         type = tvb_get_guint8(tvb, offset + 0);
1237         if (type)
1238           length = tvb_get_guint8(tvb, offset + 1);
1239         else
1240           length=0;
1241
1242         ti = proto_tree_add_text(tree, tvb, offset,
1243                                                          type?(length + 2):1,
1244                                                          "Ext: %s",
1245                                                          val_to_str(type, mip_extensions,
1246                                                                                 "Unknown ext %u"));
1247         mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1248
1249
1250         switch (type) {
1251         case ICMP_MIP_EXTENSION_PAD:
1252           /* One byte padding extension */
1253           /* Add our fields */
1254           /* type */
1255           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1256                                                   1, FALSE);
1257           offset++;
1258           break;
1259         case ICMP_MIP_MOB_AGENT_ADV:
1260           /* Mobility Agent Advertisement Extension (RFC 2002)*/
1261           /* Add our fields */
1262           /* type */
1263           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1264                                                   1, FALSE);
1265           offset++;
1266           /* length */
1267           proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1268                                                   1, FALSE);
1269           offset++;
1270           /* sequence number */
1271           proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset,
1272                                                   2, FALSE);
1273           offset+=2;
1274           /* Registration Lifetime */
1275           proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset,
1276                                                   2, FALSE);
1277           offset+=2;
1278           /* flags */
1279           flags = tvb_get_guint8(tvb, offset);
1280           ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1281                                                            1, FALSE);
1282           flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1283           proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1284           proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1285           proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1286           proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1287           proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1288           proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1289           proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1290           proto_tree_add_boolean(flags_tree, hf_icmp_mip_rt, tvb, offset, 1, flags);
1291
1292           offset++;
1293
1294           /* Reserved */
1295           proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset,
1296                                                   1, FALSE);
1297           offset++;
1298
1299           /* COAs */
1300           numCOAs = (length - 6) / 4;
1301           for (i=0; i<numCOAs; i++) {
1302                 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset,
1303                                                         4, FALSE);
1304                 offset+=4;
1305           }
1306           break;
1307         case ICMP_MIP_PREFIX_LENGTHS:
1308           /* Prefix-Lengths Extension  (RFC 2002)*/
1309           /* Add our fields */
1310           /* type */
1311           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1312                                                   1, FALSE);
1313           offset++;
1314           /* length */
1315           proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1316                                                   1, FALSE);
1317           offset++;
1318
1319           /* prefix lengths */
1320           for(i=0; i<length; i++) {
1321                 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1322                                                         1, FALSE);
1323                 offset++;
1324           }
1325           break;
1326         case ICMP_MIP_CHALLENGE:
1327           /* Challenge Extension  (RFC 3012)*/
1328           /* type */
1329           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
1330                                                   1, FALSE);
1331           offset++;
1332           /* length */
1333           proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
1334                                                   1, FALSE);
1335           offset++;
1336           /* challenge */
1337           proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset,
1338                                                   length, FALSE);
1339           offset+=length;
1340
1341           break;
1342         default:
1343           g_warning("Unknown type(%u)!  I hope the length is right (%u)",
1344                                 type, length);
1345           offset += length + 2;
1346           break;
1347         } /* switch type */
1348   } /* end while */
1349
1350 } /* dissect_mip_extensions */
1351
1352 #define MPLS_STACK_ENTRY_OBJECT_CLASS           1
1353 #define MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS      2
1354
1355 #define MPLS_STACK_ENTRY_C_TYPE                 1
1356 #define MPLS_EXTENDED_PAYLOAD_C_TYPE            1
1357
1358 /* XXX no header defines these macros ??? */
1359 #ifndef min
1360 #define min(a,b) (((a)<(b))?(a):(b))
1361 #endif
1362
1363 #ifndef max
1364 #define max(a,b) (((a)>(b))?(a):(b))
1365 #endif
1366
1367 /*
1368  * Dissect the MPLS extensions
1369  */
1370 static void
1371 dissect_mpls_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1372 {
1373     guint8          version;
1374     guint8          class_num;
1375     guint8          c_type;
1376     guint8          ttl;
1377     guint8          tmp;
1378     guint16         reserved;
1379     guint16         cksum, computed_cksum;
1380     guint16         obj_length, obj_trunc_length;
1381     proto_item      *ti, *tf_object, *tf_entry;
1382     proto_tree      *mpls_tree=NULL, *mpls_object_tree, *mpls_stack_object_tree;
1383     guint           obj_end_offset;
1384     guint           reported_length;
1385     guint           label;
1386     gboolean        unknown_object;
1387     
1388     if (!tree)
1389         return;
1390     
1391     reported_length = tvb_reported_length_remaining(tvb, offset);
1392
1393     if (reported_length < 4 /* Common header */)
1394     {
1395         proto_tree_add_text(tree, tvb, offset,
1396                             reported_length,
1397                             "MPLS Extensions (truncated)");
1398         return;
1399     }
1400     
1401     /* Add a tree for the MPLS extensions */           
1402     ti = proto_tree_add_none_format(tree, hf_icmp_mpls, tvb,
1403                                             offset, reported_length, "MPLS Extensions");
1404
1405     mpls_tree = proto_item_add_subtree(ti, ett_icmp_mpls);
1406
1407     /* Version */
1408     version = hi_nibble(tvb_get_guint8(tvb, offset));
1409     proto_tree_add_uint(mpls_tree, hf_icmp_mpls_version, tvb, offset, 1, version);
1410
1411     /* Reserved */
1412     reserved = tvb_get_ntohs(tvb, offset) & 0x0fff;
1413     proto_tree_add_uint_format(mpls_tree, hf_icmp_mpls_reserved,
1414                                 tvb, offset, 2, reserved,
1415                                 "Reserved: 0x%03x", reserved);
1416
1417     /* Checksum */
1418     cksum = tvb_get_ntohs(tvb, offset + 2);
1419     
1420     computed_cksum = ip_checksum(tvb_get_ptr(tvb, offset, reported_length),
1421                                     reported_length);
1422
1423     if (computed_cksum == 0)
1424     {
1425         proto_tree_add_uint_format(mpls_tree, hf_icmp_mpls_checksum, tvb, offset + 2, 2,
1426                                     cksum, "Checksum: 0x%04x [correct]", cksum);
1427     }
1428     else
1429     {
1430         proto_tree_add_boolean_hidden(mpls_tree, hf_icmp_mpls_checksum_bad, tvb,
1431                                             offset + 2, 2, TRUE);
1432
1433         proto_tree_add_uint_format(mpls_tree, hf_icmp_mpls_checksum, tvb, offset + 2, 2,
1434                                     cksum,
1435                                     "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1436                                     cksum, in_cksum_shouldbe(cksum, computed_cksum));
1437     }
1438
1439     if (version != 1 && version != 2)
1440     {
1441         /* Unsupported version */
1442         proto_item_append_text(ti, " (unsupported version)");
1443         return;
1444     }
1445
1446     /* Skip the common header */
1447     offset += 4;
1448
1449     /* While there is enough room to read an object */
1450     while (tvb_reported_length_remaining(tvb, offset) >= 4 /* Object header */)
1451     {
1452         /* Object length */
1453         obj_length = tvb_get_ntohs(tvb, offset);
1454
1455         obj_trunc_length =  min(obj_length, tvb_reported_length_remaining(tvb, offset));
1456
1457         obj_end_offset = offset + obj_trunc_length;
1458
1459         /* Add a subtree for this object (the text will be reset later) */
1460         tf_object = proto_tree_add_text(mpls_tree, tvb, offset,
1461                                         max(obj_trunc_length, 4),
1462                                         "Unknown object");
1463
1464         mpls_object_tree = proto_item_add_subtree(tf_object, ett_icmp_mpls_object);
1465
1466         proto_tree_add_uint(mpls_object_tree, hf_icmp_mpls_length, tvb, offset, 2, obj_length);
1467
1468         /* Class */
1469         class_num = tvb_get_guint8(tvb, offset + 2);
1470         proto_tree_add_uint(mpls_object_tree, hf_icmp_mpls_class, tvb, offset + 2, 1, class_num);
1471
1472         /* C-Type */
1473         c_type = tvb_get_guint8(tvb, offset + 3);
1474         proto_tree_add_uint(mpls_object_tree, hf_icmp_mpls_c_type, tvb, offset + 3, 1, c_type);
1475
1476         if (obj_length < 4 /* Object header */)
1477         {
1478             /* Thanks doc/README.developer :)) */
1479             proto_item_set_text(tf_object, "Object with bad length");
1480             break;
1481         }
1482
1483         /* Skip the object header */
1484         offset += 4;
1485
1486         /* Default cases will set this flag to TRUE */
1487         unknown_object = FALSE;
1488         
1489         switch (class_num)
1490         {
1491             case MPLS_STACK_ENTRY_OBJECT_CLASS:
1492                 switch (c_type)
1493                 {
1494                     case MPLS_STACK_ENTRY_C_TYPE:
1495
1496                         proto_item_set_text(tf_object, "MPLS Stack Entry");
1497
1498                         /* For each entry */
1499                         while (offset + 4 <= obj_end_offset)
1500                         {
1501                             if (tvb_reported_length_remaining(tvb, offset) < 4)
1502                             {
1503                                 /* Not enough room in the packet ! */
1504                                 break;
1505                             }
1506
1507                             /* Create a subtree for each entry (the text will be set later) */
1508                             tf_entry = proto_tree_add_text(mpls_object_tree,
1509                                                             tvb, offset, 4, " ");
1510                             mpls_stack_object_tree = proto_item_add_subtree(tf_entry, 
1511                                                                             ett_icmp_mpls_stack_object);
1512
1513                             /* Label */
1514                             label =  (guint)tvb_get_ntohs(tvb, offset);
1515                             tmp = tvb_get_guint8(tvb, offset + 2);
1516                             label = (label << 4) + (tmp >> 4);
1517
1518                             proto_tree_add_uint(mpls_stack_object_tree,
1519                                                     hf_icmp_mpls_label,
1520                                                     tvb,
1521                                                     offset,
1522                                                     3,
1523                                                     label << 4);
1524
1525                             proto_item_set_text(tf_entry, "Label: %u", label);
1526
1527                             /* Experimental field (also called "CoS") */
1528                             proto_tree_add_uint(mpls_stack_object_tree,
1529                                                     hf_icmp_mpls_exp,
1530                                                     tvb,
1531                                                     offset + 2,
1532                                                     1,
1533                                                     tmp);
1534
1535                             proto_item_append_text(tf_entry, ", Exp: %u", (tmp >> 1) & 0x07);
1536                                                     
1537                             /* Stack bit */
1538                             proto_tree_add_boolean(mpls_stack_object_tree,
1539                                                     hf_icmp_mpls_s,
1540                                                     tvb,
1541                                                     offset + 2,
1542                                                     1,
1543                                                     tmp);
1544
1545                             proto_item_append_text(tf_entry, ", S: %u", tmp  & 0x01);
1546                                                     
1547                             /* TTL */
1548                             ttl = tvb_get_guint8(tvb, offset + 3);
1549
1550                             proto_tree_add_item(mpls_stack_object_tree,
1551                                                 hf_icmp_mpls_ttl,
1552                                                 tvb,
1553                                                 offset + 3,
1554                                                 1,
1555                                                 FALSE);
1556
1557                             proto_item_append_text(tf_entry, ", TTL: %u", ttl);
1558                                                 
1559                             /* Skip the entry */
1560                             offset += 4;
1561
1562                         } /* end while */
1563
1564                         if (offset < obj_end_offset)
1565                             proto_tree_add_text(mpls_object_tree, tvb,
1566                                                 offset,
1567                                                 obj_end_offset - offset,
1568                                                 "%ld junk bytes",
1569                                                 (long)(obj_end_offset - offset));
1570
1571                         break;
1572                     default:
1573
1574                         unknown_object = TRUE;
1575
1576                         break;
1577                 } /* end switch c_type */
1578                 break;
1579             case MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS:
1580                 switch (c_type)
1581                 {
1582                     case MPLS_EXTENDED_PAYLOAD_C_TYPE:
1583                         proto_item_set_text(tf_object, "Extended Payload");
1584
1585                         /* This object contains some portion of the original packet
1586                         that could not fit in the 128 bytes of the ICMP payload */
1587                         if (obj_trunc_length > 4)
1588                             proto_tree_add_text(mpls_object_tree, tvb,
1589                                                 offset, obj_trunc_length - 4,
1590                                                 "Data (%d bytes)", obj_trunc_length - 4);
1591
1592                         break;
1593                     default:
1594
1595                         unknown_object = TRUE;
1596
1597                         break;
1598                 } /* end switch c_type */
1599                 break;
1600             default:
1601
1602                 unknown_object = TRUE;
1603
1604                 break;
1605         } /* end switch class_num */
1606         
1607         /* The switches couldn't decode the object */
1608         if (unknown_object == TRUE)
1609         {
1610             proto_item_set_text(tf_object, "Unknown object (%d/%d)", class_num, c_type);
1611             
1612             if (obj_trunc_length > 4)
1613                 proto_tree_add_text(mpls_object_tree, tvb,
1614                                     offset, obj_trunc_length - 4,
1615                                     "Data (%d bytes)", obj_trunc_length - 4);
1616         }
1617         
1618         /* */
1619         if (obj_trunc_length < obj_length)
1620             proto_item_append_text(tf_object, " (truncated)");
1621
1622         /* Go to the end of the object */
1623         offset = obj_end_offset;
1624
1625     } /* end while */
1626 } /* end dissect_mpls_extensions */
1627
1628 static const gchar *unreach_str[] = {"Network unreachable",
1629                                      "Host unreachable",
1630                                      "Protocol unreachable",
1631                                      "Port unreachable",
1632                                      "Fragmentation needed",
1633                                      "Source route failed",
1634                                      "Destination network unknown",
1635                                      "Destination host unknown",
1636                                      "Source host isolated",
1637                                      "Network administratively prohibited",
1638                                      "Host administratively prohibited",
1639                                      "Network unreachable for TOS",
1640                                      "Host unreachable for TOS",
1641                                      "Communication administratively filtered",
1642                                      "Host precedence violation",
1643                                      "Precedence cutoff in effect"};
1644
1645 #define N_UNREACH       (sizeof unreach_str / sizeof unreach_str[0])
1646
1647 static const gchar *redir_str[] = {"Redirect for network",
1648                                    "Redirect for host",
1649                                    "Redirect for TOS and network",
1650                                    "Redirect for TOS and host"};
1651
1652 #define N_REDIRECT      (sizeof redir_str / sizeof redir_str[0])
1653
1654 static const gchar *ttl_str[] = {"Time to live exceeded in transit",
1655                                  "Fragment reassembly time exceeded"};
1656
1657 #define N_TIMXCEED      (sizeof ttl_str / sizeof ttl_str[0])
1658
1659 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1660
1661 #define N_PARAMPROB     (sizeof par_str / sizeof par_str[0])
1662
1663 /*
1664  * RFC 792 for basic ICMP.
1665  * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1666  * RFC 1256 for router discovery messages.
1667  * RFC 2002 and 3012 for Mobile IP stuff.
1668  */
1669 static void
1670 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1671 {
1672   proto_tree *icmp_tree;
1673   proto_item *ti;
1674   guint8     icmp_type;
1675   guint8     icmp_code;
1676   guint      length, reported_length;
1677   guint16    cksum, computed_cksum;
1678   gchar      *type_str, *code_str;
1679   guint8     num_addrs = 0;
1680   guint8     addr_entry_size = 0;
1681   int        i;
1682   gboolean   save_in_error_pkt;
1683   tvbuff_t   *next_tvb;
1684   proto_item *item;
1685
1686   type_str="";
1687
1688   code_str=ep_alloc(64);
1689   code_str[0]=0;
1690
1691   if (check_col(pinfo->cinfo, COL_PROTOCOL))
1692     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1693   if (check_col(pinfo->cinfo, COL_INFO))
1694     col_clear(pinfo->cinfo, COL_INFO);
1695
1696   /* To do: check for runts, errs, etc. */
1697   icmp_type = tvb_get_guint8(tvb, 0);
1698   icmp_code = tvb_get_guint8(tvb, 1);
1699   cksum = tvb_get_ntohs(tvb, 2);
1700
1701   switch (icmp_type) {
1702     case ICMP_ECHOREPLY:
1703       type_str="Echo (ping) reply";
1704       break;
1705     case ICMP_UNREACH:
1706       type_str="Destination unreachable";
1707       if (icmp_code < N_UNREACH) {
1708         g_snprintf(code_str, 64, "(%s)", unreach_str[icmp_code]);
1709       } else {
1710         g_snprintf(code_str, 64, "(Unknown - error?)");
1711       }
1712       break;
1713     case ICMP_SOURCEQUENCH:
1714       type_str="Source quench (flow control)";
1715       break;
1716     case ICMP_REDIRECT:
1717       type_str="Redirect";
1718       if (icmp_code < N_REDIRECT) {
1719         g_snprintf(code_str, 64, "(%s)", redir_str[icmp_code]);
1720       } else {
1721         g_snprintf(code_str, 64, "(Unknown - error?)");
1722       }
1723       break;
1724     case ICMP_ECHO:
1725       type_str="Echo (ping) request";
1726       break;
1727     case ICMP_RTRADVERT:
1728       switch (icmp_code) {
1729       case 0: /* Mobile-Ip */
1730       case 16: /* Mobile-Ip */
1731         type_str="Mobile IP Advertisement";
1732         break;
1733       default:
1734         type_str="Router advertisement";
1735         break;
1736       } /* switch icmp_code */
1737       break;
1738     case ICMP_RTRSOLICIT:
1739       type_str="Router solicitation";
1740       break;
1741     case ICMP_TIMXCEED:
1742       type_str="Time-to-live exceeded";
1743       if (icmp_code < N_TIMXCEED) {
1744         g_snprintf(code_str, 64, "(%s)", ttl_str[icmp_code]);
1745       } else {
1746         g_snprintf(code_str, 64, "(Unknown - error?)");
1747       }
1748       break;
1749     case ICMP_PARAMPROB:
1750       type_str="Parameter problem";
1751       if (icmp_code < N_PARAMPROB) {
1752         g_snprintf(code_str, 64, "(%s)", par_str[icmp_code]);
1753       } else {
1754         g_snprintf(code_str, 64, "(Unknown - error?)");
1755       }
1756       break;
1757     case ICMP_TSTAMP:
1758       type_str="Timestamp request";
1759       break;
1760     case ICMP_TSTAMPREPLY:
1761       type_str="Timestamp reply";
1762       break;
1763     case ICMP_IREQ:
1764       type_str="Information request";
1765       break;
1766     case ICMP_IREQREPLY:
1767       type_str="Information reply";
1768       break;
1769     case ICMP_MASKREQ:
1770       type_str="Address mask request";
1771       break;
1772     case ICMP_MASKREPLY:
1773       type_str="Address mask reply";
1774       break;
1775     default:
1776       type_str="Unknown ICMP (obsolete or malformed?)";
1777       break;
1778   }
1779
1780   if (check_col(pinfo->cinfo, COL_INFO)) {
1781     col_add_str(pinfo->cinfo, COL_INFO, type_str);
1782     if (code_str[0] != '\0')
1783       col_append_fstr(pinfo->cinfo, COL_INFO, " %s", code_str);
1784   }
1785
1786   if (tree) {
1787     length = tvb_length(tvb);
1788     reported_length = tvb_reported_length(tvb);
1789     ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1790     icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1791     proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
1792                                icmp_type,
1793                                "Type: %u (%s)",
1794                                icmp_type, type_str);
1795     proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
1796                                icmp_code,
1797                                "Code: %u %s",
1798                                icmp_code, code_str);
1799
1800     if (!pinfo->fragmented && length >= reported_length) {
1801       /* The packet isn't part of a fragmented datagram and isn't
1802          truncated, so we can checksum it. */
1803
1804       computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1805                                      reported_length);
1806       if (computed_cksum == 0) {
1807         proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1808                           cksum,
1809                           "Checksum: 0x%04x [correct]", cksum);
1810       } else {
1811         item = proto_tree_add_boolean(icmp_tree, hf_icmp_checksum_bad,
1812                           tvb, 2, 2, TRUE);
1813         PROTO_ITEM_SET_HIDDEN(item);
1814         proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1815                   cksum,
1816                   "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1817                   cksum, in_cksum_shouldbe(cksum, computed_cksum));
1818       }
1819     } else {
1820       proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1821     }
1822
1823     /* Decode the second 4 bytes of the packet. */
1824     switch (icmp_type) {
1825       case ICMP_ECHOREPLY:
1826       case ICMP_ECHO:
1827       case ICMP_TSTAMP:
1828       case ICMP_TSTAMPREPLY:
1829       case ICMP_IREQ:
1830       case ICMP_IREQREPLY:
1831       case ICMP_MASKREQ:
1832       case ICMP_MASKREPLY:
1833         proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, FALSE);
1834         proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2, FALSE);
1835         break;
1836
1837       case ICMP_UNREACH:
1838         switch (icmp_code) {
1839           case ICMP_FRAG_NEEDED:
1840             proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6, 2, FALSE);
1841             break;
1842         }
1843         break;
1844
1845       case ICMP_RTRADVERT:
1846         num_addrs = tvb_get_guint8(tvb, 4);
1847         proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1848           num_addrs);
1849         addr_entry_size = tvb_get_guint8(tvb, 5);
1850         proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1851           addr_entry_size);
1852         proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1853           time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1854         break;
1855
1856       case ICMP_PARAMPROB:
1857         proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1858           tvb_get_guint8(tvb, 4));
1859         break;
1860
1861       case ICMP_REDIRECT:
1862         proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4, FALSE);
1863         break;
1864     }
1865
1866     /* Decode the additional information in the packet.  */
1867     switch (icmp_type) {
1868       case ICMP_UNREACH:
1869       case ICMP_TIMXCEED:
1870       case ICMP_PARAMPROB:
1871       case ICMP_SOURCEQUENCH:
1872       case ICMP_REDIRECT:
1873         /* Save the current value of the "we're inside an error packet"
1874            flag, and set that flag; subdissectors may treat packets
1875            that are the payload of error packets differently from
1876            "real" packets. */
1877         save_in_error_pkt = pinfo->in_error_pkt;
1878         pinfo->in_error_pkt = TRUE;
1879
1880         /* Decode the IP header and first 64 bits of data from the
1881            original datagram. */
1882         next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1883         
1884         /* There is a collision between RFC 1812 and draft-ietf-mpls-icmp-02.
1885         We don't know how to decode the 128th and following bytes of the ICMP payload.
1886         According to draft-ietf-mpls-icmp-02, these bytes should be decoded as MPLS extensions
1887         whereas RFC 1812 tells us to decode them as a portion of the original packet.
1888         Let the user decide.
1889         
1890         Here the user decided to favor MPLS extensions.
1891         Force the IP dissector to decode only the first 128 bytes. */
1892         if ((tvb_reported_length(tvb) > 8 + 128) &&
1893                         favor_icmp_mpls_ext && (tvb_get_ntohs(tvb, 8 + 2) > 128))
1894                 set_actual_length(next_tvb, 128);
1895         
1896         call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1897
1898         /* Restore the "we're inside an error packet" flag. */
1899         pinfo->in_error_pkt = save_in_error_pkt;
1900
1901         /* Decode MPLS extensions if the payload has at least 128 bytes, and
1902                 - the original packet in the ICMP payload has less than 128 bytes, or
1903                 - the user favors the MPLS extensions analysis */
1904         if ((tvb_reported_length(tvb) > 8 + 128)
1905                         && (tvb_get_ntohs(tvb, 8 + 2) <= 128 || favor_icmp_mpls_ext))
1906                 dissect_mpls_extensions(tvb, 8 + 128, icmp_tree);
1907         
1908         break;
1909
1910       case ICMP_ECHOREPLY:
1911       case ICMP_ECHO:
1912         call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1913                        icmp_tree);
1914         break;
1915
1916       case ICMP_RTRADVERT:
1917         if (addr_entry_size == 2) {
1918           for (i = 0; i < num_addrs; i++) {
1919             proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1920               "Router address: %s",
1921               ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1922             proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1923               "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1924           }
1925           if ((icmp_code == 0) || (icmp_code == 16)) {
1926                 /* Mobile-Ip */
1927                 dissect_mip_extensions(tvb, 8 + i*8, icmp_tree);
1928           }
1929         } else
1930           call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
1931                          icmp_tree);
1932         break;
1933
1934       case ICMP_TSTAMP:
1935       case ICMP_TSTAMPREPLY:
1936         proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %s after midnight UTC",
1937           time_msecs_to_str(tvb_get_ntohl(tvb, 8)));
1938         proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %s after midnight UTC",
1939           time_msecs_to_str(tvb_get_ntohl(tvb, 12)));
1940         proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %s after midnight UTC",
1941           time_msecs_to_str(tvb_get_ntohl(tvb, 16)));
1942         break;
1943
1944     case ICMP_MASKREQ:
1945     case ICMP_MASKREPLY:
1946         proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1947           ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1948         break;
1949     }
1950   }
1951 }
1952
1953 void
1954 proto_register_ip(void)
1955 {
1956         static hf_register_info hf[] = {
1957
1958                 { &hf_ip_version,
1959                 { "Version",            "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1960                         "", HFILL }},
1961
1962                 { &hf_ip_hdr_len,
1963                 { "Header Length",      "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1964                         "", HFILL }},
1965
1966                 { &hf_ip_dsfield,
1967                 { "Differentiated Services field",      "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1968                         "", HFILL }},
1969
1970                 { &hf_ip_dsfield_dscp,
1971                 { "Differentiated Services Codepoint",  "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1972                         VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1973                         "", HFILL }},
1974
1975                 { &hf_ip_dsfield_ect,
1976                 { "ECN-Capable Transport (ECT)",        "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1977                         IPDSFIELD_ECT_MASK,
1978                         "", HFILL }},
1979
1980                 { &hf_ip_dsfield_ce,
1981                 { "ECN-CE",     "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1982                         IPDSFIELD_CE_MASK,
1983                         "", HFILL }},
1984
1985                 { &hf_ip_tos,
1986                 { "Type of Service",    "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1987                         "", HFILL }},
1988
1989                 { &hf_ip_tos_precedence,
1990                 { "Precedence",         "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1991                         IPTOS_PREC_MASK,
1992                         "", HFILL }},
1993
1994                 { &hf_ip_tos_delay,
1995                 { "Delay",              "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1996                         IPTOS_LOWDELAY,
1997                         "", HFILL }},
1998
1999                 { &hf_ip_tos_throughput,
2000                 { "Throughput",         "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
2001                         IPTOS_THROUGHPUT,
2002                         "", HFILL }},
2003
2004                 { &hf_ip_tos_reliability,
2005                 { "Reliability",        "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
2006                         IPTOS_RELIABILITY,
2007                         "", HFILL }},
2008
2009                 { &hf_ip_tos_cost,
2010                 { "Cost",               "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
2011                         IPTOS_LOWCOST,
2012                         "", HFILL }},
2013
2014                 { &hf_ip_len,
2015                 { "Total Length",       "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
2016                         "", HFILL }},
2017
2018                 { &hf_ip_id,
2019                 { "Identification",     "ip.id", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2020                         "", HFILL }},
2021
2022                 { &hf_ip_dst,
2023                 { "Destination",        "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
2024                         "", HFILL }},
2025
2026                 { &hf_ip_dst_host,
2027                 { "Destination Host",           "ip.dst_host", FT_STRING, BASE_NONE, NULL, 0x0,
2028                         "", HFILL }},
2029
2030                 { &hf_ip_src,
2031                 { "Source",             "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
2032                         "", HFILL }},
2033
2034                 { &hf_ip_src_host,
2035                 { "Source Host",                "ip.src_host", FT_STRING, BASE_NONE, NULL, 0x0,
2036                         "", HFILL }},
2037
2038                 { &hf_ip_addr,
2039                 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
2040                         "", HFILL }},
2041
2042                 { &hf_ip_host,
2043                 { "Source or Destination Host", "ip.host", FT_STRING, BASE_NONE, NULL, 0x0,
2044                         "", HFILL }},
2045
2046                 { &hf_ip_flags,
2047                 { "Flags",              "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
2048                         "", HFILL }},
2049
2050                 { &hf_ip_flags_rf,
2051                 { "Reserved bit",       "ip.flags.rb", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_RF >> 12,
2052                         "", HFILL }},
2053
2054                 { &hf_ip_flags_df,
2055                 { "Don't fragment",     "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF >> 12,
2056                         "", HFILL }},
2057
2058                 { &hf_ip_flags_mf,
2059                 { "More fragments",     "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF >> 12,
2060                         "", HFILL }},
2061
2062                 { &hf_ip_frag_offset,
2063                 { "Fragment offset",    "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
2064                         "", HFILL }},
2065
2066                 { &hf_ip_ttl,
2067                 { "Time to live",       "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
2068                         "", HFILL }},
2069
2070                 { &hf_ip_proto,
2071                 { "Protocol",           "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
2072                         "", HFILL }},
2073
2074                 { &hf_ip_checksum,
2075                 { "Header checksum",    "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
2076                         "", HFILL }},
2077
2078                 { &hf_ip_checksum_good,
2079                 { "Good",       "ip.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2080                         "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
2081
2082                 { &hf_ip_checksum_bad,
2083                 { "Bad ",       "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2084                         "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
2085
2086                 { &hf_ip_fragment_overlap,
2087                 { "Fragment overlap",   "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2088                         "Fragment overlaps with other fragments", HFILL }},
2089
2090                 { &hf_ip_fragment_overlap_conflict,
2091                 { "Conflicting data in fragment overlap",       "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2092                         "Overlapping fragments contained conflicting data", HFILL }},
2093
2094                 { &hf_ip_fragment_multiple_tails,
2095                 { "Multiple tail fragments found",      "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2096                         "Several tails were found when defragmenting the packet", HFILL }},
2097
2098                 { &hf_ip_fragment_too_long_fragment,
2099                 { "Fragment too long",  "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2100                         "Fragment contained data past end of packet", HFILL }},
2101
2102                 { &hf_ip_fragment_error,
2103                 { "Defragmentation error", "ip.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2104                         "Defragmentation error due to illegal fragments", HFILL }},
2105
2106                 { &hf_ip_fragment,
2107                 { "IP Fragment", "ip.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2108                         "IP Fragment", HFILL }},
2109
2110                 { &hf_ip_fragments,
2111                 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2112                         "IP Fragments", HFILL }},
2113
2114                 { &hf_ip_reassembled_in,
2115                 { "Reassembled IP in frame", "ip.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2116                         "This IP packet is reassembled in this frame", HFILL }}
2117         };
2118         static gint *ett[] = {
2119                 &ett_ip,
2120                 &ett_ip_dsfield,
2121                 &ett_ip_tos,
2122                 &ett_ip_off,
2123                 &ett_ip_options,
2124                 &ett_ip_option_sec,
2125                 &ett_ip_option_route,
2126                 &ett_ip_option_timestamp,
2127                 &ett_ip_fragments,
2128                 &ett_ip_fragment,
2129         &ett_ip_checksum,
2130         };
2131         module_t *ip_module;
2132
2133         proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
2134         proto_register_field_array(proto_ip, hf, array_length(hf));
2135         proto_register_subtree_array(ett, array_length(ett));
2136
2137         /* subdissector code */
2138         ip_dissector_table = register_dissector_table("ip.proto",
2139             "IP protocol", FT_UINT8, BASE_DEC);
2140
2141         /* Register configuration options */
2142         ip_module = prefs_register_protocol(proto_ip, NULL);
2143         prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
2144             "Decode IPv4 TOS field as DiffServ field",
2145             "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field (see RFC2474/RFC2475)",
2146             &g_ip_dscp_actif);
2147         prefs_register_bool_preference(ip_module, "defragment",
2148                 "Reassemble fragmented IP datagrams",
2149                 "Whether fragmented IP datagrams should be reassembled",
2150                 &ip_defragment);
2151         prefs_register_bool_preference(ip_module, "summary_in_tree",
2152             "Show IP summary in protocol tree",
2153             "Whether the IP summary line should be shown in the protocol tree",
2154             &ip_summary_in_tree);
2155         prefs_register_bool_preference(ip_module, "check_checksum" ,
2156                   "Validate the IP checksum if possible",
2157                   "Whether to validate the IP checksum",
2158                   &ip_check_checksum);
2159
2160         register_dissector("ip", dissect_ip, proto_ip);
2161         register_init_routine(ip_defragment_init);
2162         ip_tap=register_tap("ip");
2163 }
2164
2165 void
2166 proto_reg_handoff_ip(void)
2167 {
2168         dissector_handle_t ip_handle;
2169
2170         data_handle = find_dissector("data");
2171         ip_handle = find_dissector("ip");
2172         dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
2173         dissector_add("ppp.protocol", PPP_IP, ip_handle);
2174         dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
2175         dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
2176         dissector_add("gre.proto", GRE_WCCP, ip_handle);
2177         dissector_add("llc.dsap", SAP_IP, ip_handle);
2178         dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
2179         dissector_add("null.type", BSD_AF_INET, ip_handle);
2180         dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
2181         dissector_add("osinl.excl", NLPID_IP, ip_handle);
2182         dissector_add("fr.ietf", NLPID_IP, ip_handle);
2183         dissector_add("x.25.spi", NLPID_IP, ip_handle);
2184         dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1051, ip_handle);
2185         dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1201, ip_handle);
2186         dissector_add_handle("udp.port", ip_handle);
2187 }
2188
2189 void
2190 proto_register_icmp(void)
2191 {
2192   static hf_register_info hf[] = {
2193
2194     { &hf_icmp_type,
2195       { "Type",         "icmp.type",            FT_UINT8, BASE_DEC,     NULL, 0x0,
2196         "", HFILL }},
2197
2198     { &hf_icmp_code,
2199       { "Code",         "icmp.code",            FT_UINT8, BASE_HEX,     NULL, 0x0,
2200         "", HFILL }},
2201
2202     { &hf_icmp_checksum,
2203       { "Checksum",     "icmp.checksum",        FT_UINT16, BASE_HEX,    NULL, 0x0,
2204         "", HFILL }},
2205
2206     { &hf_icmp_checksum_bad,
2207       { "Bad Checksum", "icmp.checksum_bad",    FT_BOOLEAN, BASE_NONE,  NULL, 0x0,
2208         "", HFILL }},
2209
2210     { &hf_icmp_ident,
2211       {"Identifier", "icmp.ident",              FT_UINT16, BASE_HEX,    NULL, 0x0,
2212        "", HFILL }},
2213
2214     { &hf_icmp_seq_num,
2215       {"Sequence number", "icmp.seq",           FT_UINT16, BASE_HEX,    NULL, 0x0,
2216        "", HFILL }},
2217
2218     { &hf_icmp_mtu,
2219       {"MTU of next hop", "icmp.mtu",           FT_UINT16, BASE_DEC,    NULL, 0x0,
2220        "", HFILL}},
2221
2222     { &hf_icmp_redir_gw,
2223       {"Gateway address", "icmp.redir_gw",      FT_IPv4, BASE_NONE,     NULL, 0x0,
2224        "", HFILL }},
2225
2226     { &hf_icmp_mip_type,
2227       { "Extension Type", "icmp.mip.type",      FT_UINT8, BASE_DEC,
2228         VALS(mip_extensions), 0x0,"", HFILL}},
2229
2230     { &hf_icmp_mip_length,
2231       { "Length", "icmp.mip.length",            FT_UINT8, BASE_DEC, NULL, 0x0,
2232         "", HFILL}},
2233
2234     { &hf_icmp_mip_prefix_length,
2235       { "Prefix Length", "icmp.mip.prefixlength",  FT_UINT8, BASE_DEC, NULL, 0x0,
2236         "", HFILL}},
2237
2238     { &hf_icmp_mip_seq,
2239       { "Sequence Number", "icmp.mip.seq",      FT_UINT16, BASE_DEC, NULL, 0x0,
2240         "", HFILL}},
2241
2242     { &hf_icmp_mip_life,
2243       { "Registration Lifetime", "icmp.mip.life",  FT_UINT16, BASE_DEC, NULL, 0x0,
2244         "", HFILL}},
2245
2246     { &hf_icmp_mip_flags,
2247       { "Flags", "icmp.mip.flags",            FT_UINT8, BASE_HEX, NULL, 0x0,
2248         "", HFILL}},
2249
2250     { &hf_icmp_mip_r,
2251       { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
2252         "Registration with this FA is required", HFILL }},
2253
2254     { &hf_icmp_mip_b,
2255       { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
2256         "This FA will not accept requests at this time", HFILL }},
2257
2258     { &hf_icmp_mip_h,
2259       { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
2260         "Home Agent Services Offered", HFILL }},
2261
2262     { &hf_icmp_mip_f,
2263       { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
2264         "Foreign Agent Services Offered", HFILL }},
2265
2266     { &hf_icmp_mip_m,
2267       { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
2268         "Minimal encapsulation tunneled datagram support", HFILL }},
2269
2270     { &hf_icmp_mip_g,
2271       { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
2272         "GRE encapsulated tunneled datagram support", HFILL }},
2273
2274     { &hf_icmp_mip_v,
2275       { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
2276         "Van Jacobson Header Compression Support", HFILL }},
2277
2278     { &hf_icmp_mip_rt,
2279       { "Reverse tunneling", "icmp.mip.rt", FT_BOOLEAN, 8, NULL, 1,
2280        "Reverse tunneling support", HFILL }},
2281
2282
2283     { &hf_icmp_mip_reserved,
2284       { "Reserved", "icmp.mip.reserved",     FT_UINT8, BASE_HEX, NULL, 0x0,
2285         "", HFILL}},
2286
2287     { &hf_icmp_mip_coa,
2288       { "Care-Of-Address", "icmp.mip.coa",    FT_IPv4, BASE_NONE, NULL, 0x0,
2289         "", HFILL}},
2290
2291     { &hf_icmp_mip_challenge,
2292       { "Challenge", "icmp.mip.challenge",    FT_BYTES, BASE_NONE, NULL, 0x0,
2293         "", HFILL}},
2294
2295     { &hf_icmp_mpls,
2296       { "ICMP Extensions for MPLS",     "icmp.mpls",    FT_NONE, BASE_NONE,     NULL, 0x0,
2297         "", HFILL }},
2298     
2299         { &hf_icmp_mpls_version,
2300                 { "Version",            "icmp.mpls.version", FT_UINT8, BASE_DEC, NULL, 0x0,
2301                         "", HFILL }},
2302             
2303     { &hf_icmp_mpls_reserved,
2304       { "Reserved",     "icmp.mpls.res",        FT_UINT16, BASE_HEX,    NULL, 0x0,
2305         "", HFILL }},
2306
2307         { &hf_icmp_mpls_checksum,
2308       { "Checksum",     "icmp.mpls.checksum",   FT_UINT16, BASE_HEX,    NULL, 0x0,
2309         "", HFILL }},
2310
2311         { &hf_icmp_mpls_checksum_bad,
2312       { "Bad Checksum", "icmp.mpls.checksum_bad",       FT_BOOLEAN, BASE_NONE,  NULL, 0x0,
2313         "", HFILL }},
2314
2315         { &hf_icmp_mpls_length,
2316       { "Length",       "icmp.mpls.length",     FT_UINT16, BASE_HEX,    NULL, 0x0,
2317         "", HFILL }},
2318
2319         { &hf_icmp_mpls_class,
2320                 { "Class",      "icmp.mpls.class", FT_UINT8, BASE_DEC, NULL, 0x0,
2321                         "", HFILL }},
2322
2323         { &hf_icmp_mpls_c_type,
2324                 { "C-Type",     "icmp.mpls.ctype", FT_UINT8, BASE_DEC, NULL, 0x0,
2325                         "", HFILL }},
2326
2327         { &hf_icmp_mpls_label,
2328                 { "Label",      "icmp.mpls.label", FT_UINT24, BASE_DEC, NULL, 0x00fffff0,
2329                         "", HFILL }},
2330
2331         { &hf_icmp_mpls_exp,
2332                 { "Experimental",       "icmp.mpls.exp", FT_UINT24, BASE_DEC,
2333                         NULL, 0x0e,
2334                         "", HFILL }},
2335
2336         { &hf_icmp_mpls_s,
2337                 { "Stack bit",  "icmp.mpls.s", FT_BOOLEAN, 24, TFS(&flags_set_truth), 0x01,
2338                         "", HFILL }},
2339
2340         { &hf_icmp_mpls_ttl,
2341                 { "Time to live",       "icmp.mpls.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
2342                         "", HFILL }}
2343
2344   };
2345   static gint *ett[] = {
2346     &ett_icmp,
2347         &ett_icmp_mip,
2348         &ett_icmp_mip_flags,
2349         /* MPLS extensions */
2350         &ett_icmp_mpls,
2351         &ett_icmp_mpls_object,
2352         &ett_icmp_mpls_stack_object
2353   };
2354   
2355   module_t *icmp_module;
2356   
2357   proto_icmp = proto_register_protocol("Internet Control Message Protocol",
2358                                        "ICMP", "icmp");
2359   proto_register_field_array(proto_icmp, hf, array_length(hf));
2360   proto_register_subtree_array(ett, array_length(ett));
2361   
2362   icmp_module = prefs_register_protocol(proto_icmp, NULL);
2363   
2364   prefs_register_bool_preference(icmp_module, "favor_icmp_mpls",
2365             "Favor ICMP extensions for MPLS",
2366             "Whether the 128th and following bytes of the ICMP payload should be decoded as MPLS extensions or as a portion of the original packet",
2367             &favor_icmp_mpls_ext);
2368 }
2369
2370 void
2371 proto_reg_handoff_icmp(void)
2372 {
2373   dissector_handle_t icmp_handle;
2374
2375   /*
2376    * Get handle for the IP dissector.
2377    */
2378   ip_handle = find_dissector("ip");
2379   ipv6_handle = find_dissector("ipv6");
2380
2381   icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
2382   dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);
2383 }