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