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