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