Initial support for writing NetXRay 2.x (Windows Sniffer) format
[obnox/wireshark/wip.git] / packet-ip.c
1 /* packet-ip.c
2  * Routines for IP and miscellaneous IP protocol packet disassembly
3  *
4  * $Id: packet-ip.c,v 1.165 2002/03/31 21:43:51 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 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32
33 #ifdef HAVE_NETINET_IN_H
34 # include <netinet/in.h>
35 #endif
36
37 #include <stdio.h>
38 #include <string.h>
39 #include <glib.h>
40
41 #ifdef NEED_SNPRINTF_H
42 # include "snprintf.h"
43 #endif
44
45 #include <epan/packet.h>
46 #include <epan/resolv.h>
47 #include "ipproto.h"
48 #include "prefs.h"
49 #include "reassemble.h"
50 #include "etypes.h"
51 #include "greproto.h"
52 #include "ppptypes.h"
53 #include "llcsaps.h"
54 #include "aftypes.h"
55 #include "packet-ip.h"
56 #include "packet-ipsec.h"
57 #include "in_cksum.h"
58 #include "nlpid.h"
59
60 static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
61
62 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
63 static gboolean g_ip_dscp_actif = TRUE;
64
65 /* Defragment fragmented IP datagrams */
66 static gboolean ip_defragment = FALSE;
67
68 /* Place IP summary in proto tree */
69 static gboolean ip_summary_in_tree = TRUE;
70
71 static int proto_ip = -1;
72 static int hf_ip_version = -1;
73 static int hf_ip_hdr_len = -1;
74 static int hf_ip_dsfield = -1;
75 static int hf_ip_dsfield_dscp = -1;
76 static int hf_ip_dsfield_ect = -1;
77 static int hf_ip_dsfield_ce = -1;
78 static int hf_ip_tos = -1;
79 static int hf_ip_tos_precedence = -1;
80 static int hf_ip_tos_delay = -1;
81 static int hf_ip_tos_throughput = -1;
82 static int hf_ip_tos_reliability = -1;
83 static int hf_ip_tos_cost = -1;
84 static int hf_ip_len = -1;
85 static int hf_ip_id = -1;
86 static int hf_ip_dst = -1;
87 static int hf_ip_src = -1;
88 static int hf_ip_addr = -1;
89 static int hf_ip_flags = -1;
90 static int hf_ip_flags_df = -1;
91 static int hf_ip_flags_mf = -1;
92 static int hf_ip_frag_offset = -1;
93 static int hf_ip_ttl = -1;
94 static int hf_ip_proto = -1;
95 static int hf_ip_checksum = -1;
96 static int hf_ip_checksum_bad = -1;
97 static int hf_ip_fragments = -1;
98 static int hf_ip_fragment = -1;
99 static int hf_ip_fragment_overlap = -1;
100 static int hf_ip_fragment_overlap_conflict = -1;
101 static int hf_ip_fragment_multiple_tails = -1;
102 static int hf_ip_fragment_too_long_fragment = -1;
103 static int hf_ip_fragment_error = -1;
104
105 static gint ett_ip = -1;
106 static gint ett_ip_dsfield = -1;
107 static gint ett_ip_tos = -1;
108 static gint ett_ip_off = -1;
109 static gint ett_ip_options = -1;
110 static gint ett_ip_option_sec = -1;
111 static gint ett_ip_option_route = -1;
112 static gint ett_ip_option_timestamp = -1;
113 static gint ett_ip_fragments = -1;
114 static gint ett_ip_fragment  = -1;
115
116 /* Used by IPv6 as well, so not static */
117 dissector_table_t ip_dissector_table;
118
119 static dissector_handle_t ip_handle;
120 static dissector_handle_t data_handle;
121
122 static int proto_icmp = -1;
123 static int hf_icmp_type = -1;
124 static int hf_icmp_code = -1;
125 static int hf_icmp_checksum = -1;
126 static int hf_icmp_checksum_bad = -1;
127
128 /* Mobile ip */
129 static int hf_icmp_mip_type = -1;
130 static int hf_icmp_mip_length = -1;
131 static int hf_icmp_mip_prefix_length = -1;
132 static int hf_icmp_mip_seq = -1;
133 static int hf_icmp_mip_life = -1;
134 static int hf_icmp_mip_flags = -1;
135 static int hf_icmp_mip_r = -1;
136 static int hf_icmp_mip_b = -1;
137 static int hf_icmp_mip_h = -1;
138 static int hf_icmp_mip_f = -1;
139 static int hf_icmp_mip_m = -1;
140 static int hf_icmp_mip_g = -1;
141 static int hf_icmp_mip_v = -1;
142 static int hf_icmp_mip_res = -1;
143 static int hf_icmp_mip_reserved = -1;
144 static int hf_icmp_mip_coa = -1;
145 static int hf_icmp_mip_challenge = -1;
146
147 static gint ett_icmp = -1;
148 static gint ett_icmp_mip = -1;
149 static gint ett_icmp_mip_flags = -1;
150
151 /* ICMP definitions */
152
153 #define ICMP_ECHOREPLY     0
154 #define ICMP_UNREACH       3
155 #define ICMP_SOURCEQUENCH  4
156 #define ICMP_REDIRECT      5
157 #define ICMP_ECHO          8
158 #define ICMP_RTRADVERT     9
159 #define ICMP_RTRSOLICIT   10
160 #define ICMP_TIMXCEED     11
161 #define ICMP_PARAMPROB    12
162 #define ICMP_TSTAMP       13
163 #define ICMP_TSTAMPREPLY  14
164 #define ICMP_IREQ         15
165 #define ICMP_IREQREPLY    16
166 #define ICMP_MASKREQ      17
167 #define ICMP_MASKREPLY    18
168
169 /* ICMP UNREACHABLE */
170
171 #define ICMP_NET_UNREACH        0       /* Network Unreachable */
172 #define ICMP_HOST_UNREACH       1       /* Host Unreachable */
173 #define ICMP_PROT_UNREACH       2       /* Protocol Unreachable */
174 #define ICMP_PORT_UNREACH       3       /* Port Unreachable */
175 #define ICMP_FRAG_NEEDED        4       /* Fragmentation Needed/DF set */
176 #define ICMP_SR_FAILED          5       /* Source Route failed */
177 #define ICMP_NET_UNKNOWN        6
178 #define ICMP_HOST_UNKNOWN       7
179 #define ICMP_HOST_ISOLATED      8
180 #define ICMP_NET_ANO            9
181 #define ICMP_HOST_ANO           10
182 #define ICMP_NET_UNR_TOS        11
183 #define ICMP_HOST_UNR_TOS       12
184 #define ICMP_PKT_FILTERED       13      /* Packet filtered */
185 #define ICMP_PREC_VIOLATION     14      /* Precedence violation */
186 #define ICMP_PREC_CUTOFF        15      /* Precedence cut off */
187
188
189 /* IP structs and definitions */
190
191 typedef struct _e_ip 
192    {
193    guint8  ip_v_hl; /* combines ip_v and ip_hl */
194    guint8  ip_tos;
195    guint16 ip_len;
196    guint16 ip_id;
197    guint16 ip_off;
198    guint8  ip_ttl;
199    guint8  ip_p;
200    guint16 ip_sum;
201    guint32 ip_src;
202    guint32 ip_dst;
203    } e_ip;
204
205 /* Offsets of fields within an IP header. */
206 #define IPH_V_HL        0
207 #define IPH_TOS         1
208 #define IPH_LEN         2
209 #define IPH_ID          4
210 #define IPH_TTL         6
211 #define IPH_OFF         8
212 #define IPH_P           9
213 #define IPH_SUM         10
214 #define IPH_SRC         12
215 #define IPH_DST         16
216
217 /* Minimum IP header length. */
218 #define IPH_MIN_LEN     20
219
220 /* IP flags. */
221 #define IP_CE           0x8000          /* Flag: "Congestion"           */
222 #define IP_DF           0x4000          /* Flag: "Don't Fragment"       */
223 #define IP_MF           0x2000          /* Flag: "More Fragments"       */
224 #define IP_OFFSET       0x1FFF          /* "Fragment Offset" part       */
225
226 /* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
227 #define IPDSFIELD_DSCP_MASK     0xFC
228 #define IPDSFIELD_ECN_MASK     0x03
229 #define IPDSFIELD_DSCP_SHIFT    2
230 #define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
231 #define IPDSFIELD_ECN(dsfield)  ((dsfield)&IPDSFIELD_ECN_MASK)
232 #define IPDSFIELD_DSCP_DEFAULT  0x00
233 #define IPDSFIELD_DSCP_CS1      0x08
234 #define IPDSFIELD_DSCP_CS2      0x10
235 #define IPDSFIELD_DSCP_CS3      0x18
236 #define IPDSFIELD_DSCP_CS4      0x20
237 #define IPDSFIELD_DSCP_CS5      0x28
238 #define IPDSFIELD_DSCP_CS6      0x30
239 #define IPDSFIELD_DSCP_CS7      0x38
240 #define IPDSFIELD_DSCP_AF11     0x0A
241 #define IPDSFIELD_DSCP_AF12     0x0C
242 #define IPDSFIELD_DSCP_AF13     0x0E
243 #define IPDSFIELD_DSCP_AF21     0x12
244 #define IPDSFIELD_DSCP_AF22     0x14
245 #define IPDSFIELD_DSCP_AF23     0x16
246 #define IPDSFIELD_DSCP_AF31     0x1A
247 #define IPDSFIELD_DSCP_AF32     0x1C
248 #define IPDSFIELD_DSCP_AF33     0x1E
249 #define IPDSFIELD_DSCP_AF41     0x22
250 #define IPDSFIELD_DSCP_AF42     0x24
251 #define IPDSFIELD_DSCP_AF43     0x26
252 #define IPDSFIELD_DSCP_EF       0x2E
253 #define IPDSFIELD_ECT_MASK      0x02
254 #define IPDSFIELD_CE_MASK       0x01
255
256 /* IP TOS, superseded by the DS Field, RFC 2474. */
257 #define IPTOS_TOS_MASK    0x1E
258 #define IPTOS_TOS(tos)    ((tos) & IPTOS_TOS_MASK)
259 #define IPTOS_NONE        0x00
260 #define IPTOS_LOWCOST     0x02
261 #define IPTOS_RELIABILITY 0x04
262 #define IPTOS_THROUGHPUT  0x08
263 #define IPTOS_LOWDELAY    0x10
264 #define IPTOS_SECURITY    0x1E
265
266 #define IPTOS_PREC_MASK         0xE0
267 #define IPTOS_PREC_SHIFT        5
268 #define IPTOS_PREC(tos)         (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
269 #define IPTOS_PREC_NETCONTROL           7
270 #define IPTOS_PREC_INTERNETCONTROL      6
271 #define IPTOS_PREC_CRITIC_ECP           5
272 #define IPTOS_PREC_FLASHOVERRIDE        4
273 #define IPTOS_PREC_FLASH                3
274 #define IPTOS_PREC_IMMEDIATE            2
275 #define IPTOS_PREC_PRIORITY             1
276 #define IPTOS_PREC_ROUTINE              0
277
278 /* IP options */
279 #define IPOPT_COPY              0x80
280
281 #define IPOPT_CONTROL           0x00
282 #define IPOPT_RESERVED1         0x20
283 #define IPOPT_MEASUREMENT       0x40
284 #define IPOPT_RESERVED2         0x60
285
286 #define IPOPT_END       (0 |IPOPT_CONTROL)
287 #define IPOPT_NOOP      (1 |IPOPT_CONTROL)
288 #define IPOPT_SEC       (2 |IPOPT_CONTROL|IPOPT_COPY)
289 #define IPOPT_LSRR      (3 |IPOPT_CONTROL|IPOPT_COPY)
290 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
291 #define IPOPT_RR        (7 |IPOPT_CONTROL)
292 #define IPOPT_SID       (8 |IPOPT_CONTROL|IPOPT_COPY)
293 #define IPOPT_SSRR      (9 |IPOPT_CONTROL|IPOPT_COPY)
294 #define IPOPT_RA        (20|IPOPT_CONTROL|IPOPT_COPY)
295
296 /* IP option lengths */
297 #define IPOLEN_SEC      11
298 #define IPOLEN_LSRR_MIN 3
299 #define IPOLEN_TIMESTAMP_MIN 5
300 #define IPOLEN_RR_MIN   3
301 #define IPOLEN_SID      4
302 #define IPOLEN_SSRR_MIN 3
303 #define IPOLEN_RA       4
304
305 #define IPSEC_UNCLASSIFIED      0x0000
306 #define IPSEC_CONFIDENTIAL      0xF135
307 #define IPSEC_EFTO              0x789A
308 #define IPSEC_MMMM              0xBC4D
309 #define IPSEC_RESTRICTED        0xAF13
310 #define IPSEC_SECRET            0xD788
311 #define IPSEC_TOPSECRET         0x6BC5
312 #define IPSEC_RESERVED1         0x35E2
313 #define IPSEC_RESERVED2         0x9AF1
314 #define IPSEC_RESERVED3         0x4D78
315 #define IPSEC_RESERVED4         0x24BD
316 #define IPSEC_RESERVED5         0x135E
317 #define IPSEC_RESERVED6         0x89AF
318 #define IPSEC_RESERVED7         0xC4D6
319 #define IPSEC_RESERVED8         0xE26B
320
321 #define IPOPT_TS_TSONLY         0               /* timestamps only */
322 #define IPOPT_TS_TSANDADDR      1               /* timestamps and addresses */
323 #define IPOPT_TS_PRESPEC        3               /* specified modules only */
324
325 /*
326  * defragmentation of IPv4
327  */
328 static GHashTable *ip_fragment_table = NULL;
329
330 static void
331 ip_defragment_init(void)
332 {
333   fragment_table_init(&ip_fragment_table);
334 }
335
336 void
337 capture_ip(const u_char *pd, int offset, int len, packet_counts *ld) {
338   if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
339     ld->other++;
340     return;
341   }
342   switch (pd[offset + 9]) {
343     case IP_PROTO_SCTP:
344       ld->sctp++;
345       break;
346     case IP_PROTO_TCP:
347       ld->tcp++;
348       break;
349     case IP_PROTO_UDP:
350       ld->udp++;
351       break;
352     case IP_PROTO_ICMP:
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   struct in_addr 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.s_addr == 0) ? "-" : (char *)get_hostname(addr.s_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   struct in_addr 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.s_addr == 0) ? "-" :  (char *)get_hostname(addr.s_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   u_char            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 const true_false_string flags_set_truth = {
802   "Set",
803   "Not set"
804 };
805
806 static guint16 ip_checksum(const guint8 *ptr, int len)
807 {
808         vec_t cksum_vec[1];
809
810         cksum_vec[0].ptr = ptr;
811         cksum_vec[0].len = len;
812         return in_cksum(&cksum_vec[0], 1);
813 }
814
815 static void
816 dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
817 {
818   e_ip       iph;
819   proto_tree *ip_tree = NULL, *field_tree;
820   proto_item *ti, *tf;
821   int        offset = 0;
822   guint      hlen, optlen, len;
823   guint16    flags;
824   guint8     nxt;
825   guint16    ipsum;
826   fragment_data *ipfd_head;
827   tvbuff_t   *next_tvb;
828   gboolean   update_col_info = TRUE;
829   gboolean   save_fragmented;
830
831   if (check_col(pinfo->cinfo, COL_PROTOCOL))
832     col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
833   if (check_col(pinfo->cinfo, COL_INFO))
834     col_clear(pinfo->cinfo, COL_INFO);
835
836   /* Avoids alignment problems on many architectures. */
837   tvb_memcpy(tvb, (guint8 *)&iph, offset, sizeof(e_ip));
838   iph.ip_len = ntohs(iph.ip_len);
839   iph.ip_id  = ntohs(iph.ip_id);
840   iph.ip_off = ntohs(iph.ip_off);
841   iph.ip_sum = ntohs(iph.ip_sum);
842
843   /* Length of IP datagram.
844      XXX - what if this is greater than the reported length of the
845      tvbuff?  This could happen, for example, in an IP datagram
846      inside an ICMP datagram; we need to somehow let the
847      dissector we call know that, as it might want to avoid
848      doing its checksumming. */
849   len = iph.ip_len;
850
851   /* Adjust the length of this tvbuff to include only the IP datagram. */
852   set_actual_length(tvb, len);
853
854   hlen = lo_nibble(iph.ip_v_hl) * 4;    /* IP header length, in bytes */
855  
856   if (tree) {
857     if (ip_summary_in_tree && hlen >= IPH_MIN_LEN) {
858       ti = proto_tree_add_protocol_format(tree, proto_ip, tvb, offset, hlen,
859                 "Internet Protocol, Src Addr: %s (%s), Dst Addr: %s (%s)",
860                 get_hostname(iph.ip_src), ip_to_str((guint8 *) &iph.ip_src),
861                 get_hostname(iph.ip_dst), ip_to_str((guint8 *) &iph.ip_dst));
862     } else {
863       ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
864     }
865     ip_tree = proto_item_add_subtree(ti, ett_ip);
866   }
867
868   if (hlen < IPH_MIN_LEN) {
869     if (check_col(pinfo->cinfo, COL_INFO))
870       col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
871        hlen, IPH_MIN_LEN);
872     if (tree) {
873       proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
874        "Header length: %u bytes (bogus, must be at least %u)", hlen,
875        IPH_MIN_LEN);
876     }
877     return;
878   }
879
880   /*
881    * Compute the checksum of the IP header.
882    */
883   ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
884
885   if (tree) {
886     proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1, hi_nibble(iph.ip_v_hl));
887     proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
888         "Header length: %u bytes", hlen);
889
890     if (g_ip_dscp_actif) {
891       tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph.ip_tos,
892            "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph.ip_tos,
893            IPDSFIELD_DSCP(iph.ip_tos), val_to_str(IPDSFIELD_DSCP(iph.ip_tos), dscp_vals,
894            "Unknown DSCP"),IPDSFIELD_ECN(iph.ip_tos));
895
896       field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
897       proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph.ip_tos);
898       proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph.ip_tos);
899       proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph.ip_tos);
900     } else {
901       tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph.ip_tos,
902           "Type of service: 0x%02x (%s)", iph.ip_tos,
903           val_to_str( IPTOS_TOS(iph.ip_tos), iptos_vals, "Unknown") );
904
905       field_tree = proto_item_add_subtree(tf, ett_ip_tos);
906       proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph.ip_tos);
907       proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph.ip_tos);
908       proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph.ip_tos);
909       proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph.ip_tos);
910       proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph.ip_tos);
911     }
912     proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset +  2, 2, iph.ip_len);
913     proto_tree_add_uint(ip_tree, hf_ip_id, tvb, offset +  4, 2, iph.ip_id);
914
915     flags = (iph.ip_off & (IP_DF|IP_MF)) >> 12;
916     tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset +  6, 1, flags);
917     field_tree = proto_item_add_subtree(tf, ett_ip_off);
918     proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags),
919     proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags),
920
921     proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset +  6, 2,
922       (iph.ip_off & IP_OFFSET)*8);
923
924     proto_tree_add_uint(ip_tree, hf_ip_ttl, tvb, offset +  8, 1, iph.ip_ttl);
925     proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset +  9, 1, iph.ip_p,
926         "Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
927
928     if (ipsum == 0) {
929         proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
930               "Header checksum: 0x%04x (correct)", iph.ip_sum);
931     }
932     else {
933         proto_tree_add_boolean_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
934         proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph.ip_sum,
935           "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph.ip_sum,
936           in_cksum_shouldbe(iph.ip_sum, ipsum));
937     }
938
939     proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, iph.ip_src);
940     proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, iph.ip_dst);
941     proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, iph.ip_src);
942     proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, iph.ip_dst);
943
944     /* Decode IP options, if any. */
945     if (hlen > sizeof (e_ip)) {
946       /* There's more than just the fixed-length header.  Decode the
947          options. */
948       optlen = hlen - sizeof (e_ip);    /* length of options, in bytes */
949       tf = proto_tree_add_text(ip_tree, tvb, offset +  20, optlen,
950         "Options: (%u bytes)", optlen);
951       field_tree = proto_item_add_subtree(tf, ett_ip_options);
952       dissect_ip_tcp_options(tvb, offset + 20, optlen,
953          ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
954     }
955   }
956
957   pinfo->ipproto = iph.ip_p;
958
959   pinfo->iplen = iph.ip_len;
960
961   pinfo->iphdrlen = lo_nibble(iph.ip_v_hl);
962
963   SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
964   SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
965   SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
966   SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
967
968   /* Skip over header + options */
969   offset += hlen;
970   nxt = iph.ip_p;       /* XXX - what if this isn't the same for all fragments? */
971
972   /* If ip_defragment is on, this is a fragment, we have all the data
973    * in the fragment, and the header checksum is valid, then just add
974    * the fragment to the hashtable.
975    */
976   save_fragmented = pinfo->fragmented;
977   if (ip_defragment && (iph.ip_off & (IP_MF|IP_OFFSET)) &&
978         tvb_reported_length(tvb) <= tvb_length(tvb) && ipsum == 0) {
979     ipfd_head = fragment_add(tvb, offset, pinfo, iph.ip_id,
980                              ip_fragment_table,
981                              (iph.ip_off & IP_OFFSET)*8,
982                              pinfo->iplen - (pinfo->iphdrlen*4),
983                              iph.ip_off & IP_MF);
984
985     if (ipfd_head != NULL) {
986       fragment_data *ipfd;
987       proto_tree *ft=NULL;
988       proto_item *fi=NULL;
989
990       /* OK, we have the complete reassembled payload.
991          Allocate a new tvbuff, referring to the reassembled payload. */
992       next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen,
993         ipfd_head->datalen);
994
995       /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
996          were handed refers, so it'll get cleaned up when that tvbuff
997          is cleaned up. */
998       tvb_set_child_real_data_tvbuff(tvb, next_tvb);
999
1000       /* Add the defragmented data to the data source list. */
1001       add_new_data_source(pinfo->fd, next_tvb, "Reassembled IPv4");
1002
1003       /* It's not fragmented. */
1004       pinfo->fragmented = FALSE;
1005
1006       /* show all fragments */
1007       fi = proto_tree_add_item(ip_tree, hf_ip_fragments, 
1008                 next_tvb, 0, -1, FALSE);
1009       ft = proto_item_add_subtree(fi, ett_ip_fragments);
1010       for (ipfd=ipfd_head->next; ipfd; ipfd=ipfd->next){
1011         if (ipfd->flags & (FD_OVERLAP|FD_OVERLAPCONFLICT
1012                           |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
1013           /* this fragment has some flags set, create a subtree 
1014            * for it and display the flags.
1015            */
1016           proto_tree *fet=NULL;
1017           proto_item *fei=NULL;
1018           int hf;
1019
1020           if (ipfd->flags & (FD_OVERLAPCONFLICT
1021                       |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
1022             hf = hf_ip_fragment_error;
1023           } else {
1024             hf = hf_ip_fragment;
1025           }
1026           fei = proto_tree_add_none_format(ft, hf, 
1027                    next_tvb, ipfd->offset, ipfd->len,
1028                    "Frame:%u payload:%u-%u",
1029                    ipfd->frame,
1030                    ipfd->offset,
1031                    ipfd->offset+ipfd->len-1
1032           );
1033           fet = proto_item_add_subtree(fei, ett_ip_fragment);
1034           if (ipfd->flags&FD_OVERLAP) {
1035             proto_tree_add_boolean(fet, 
1036                  hf_ip_fragment_overlap, next_tvb, 0, 0, 
1037                  TRUE);
1038           }
1039           if (ipfd->flags&FD_OVERLAPCONFLICT) {
1040             proto_tree_add_boolean(fet, 
1041                  hf_ip_fragment_overlap_conflict, next_tvb, 0, 0, 
1042                  TRUE);
1043           }
1044           if (ipfd->flags&FD_MULTIPLETAILS) {
1045             proto_tree_add_boolean(fet, 
1046                  hf_ip_fragment_multiple_tails, next_tvb, 0, 0, 
1047                  TRUE);
1048           }
1049           if (ipfd->flags&FD_TOOLONGFRAGMENT) {
1050             proto_tree_add_boolean(fet, 
1051                  hf_ip_fragment_too_long_fragment, next_tvb, 0, 0, 
1052                  TRUE);
1053           }
1054         } else {
1055           /* nothing of interest for this fragment */
1056           proto_tree_add_none_format(ft, hf_ip_fragment, 
1057                    next_tvb, ipfd->offset, ipfd->len,
1058                    "Frame:%u payload:%u-%u",
1059                    ipfd->frame,
1060                    ipfd->offset,
1061                    ipfd->offset+ipfd->len-1
1062           );
1063         }
1064       }
1065       if (ipfd_head->flags & (FD_OVERLAPCONFLICT
1066                         |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
1067         if (check_col(pinfo->cinfo, COL_INFO)) {
1068           col_set_str(pinfo->cinfo, COL_INFO, "[Illegal fragments]");
1069           update_col_info = FALSE;
1070         }
1071       }
1072     } else {
1073       /* We don't have the complete reassembled payload. */
1074       next_tvb = NULL;
1075     }
1076   } else {
1077     /* If this is the first fragment, dissect its contents, otherwise
1078        just show it as a fragment.
1079
1080        XXX - if we eventually don't save the reassembled contents of all
1081        fragmented datagrams, we may want to always reassemble. */
1082     if (iph.ip_off & IP_OFFSET) {
1083       /* Not the first fragment - don't dissect it. */
1084       next_tvb = NULL;
1085     } else {
1086       /* First fragment, or not fragmented.  Dissect what we have here. */
1087
1088       /* Get a tvbuff for the payload. */
1089       next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1090
1091       /*
1092        * If this is the first fragment, but not the only fragment,
1093        * tell the next protocol that.
1094        */
1095       if (iph.ip_off & IP_MF)
1096         pinfo->fragmented = TRUE;
1097       else
1098         pinfo->fragmented = FALSE;
1099     }
1100   }
1101
1102   if (next_tvb == NULL) {
1103     /* Just show this as a fragment. */
1104     if (check_col(pinfo->cinfo, COL_INFO))
1105       col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
1106         ipprotostr(iph.ip_p), iph.ip_p, (iph.ip_off & IP_OFFSET) * 8);
1107     call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, tree);
1108     pinfo->fragmented = save_fragmented;
1109     return;
1110   }
1111
1112   /* Hand off to the next protocol.
1113
1114      XXX - setting the columns only after trying various dissectors means
1115      that if one of those dissectors throws an exception, the frame won't
1116      even be labelled as an IP frame; ideally, if a frame being dissected
1117      throws an exception, it'll be labelled as a mangled frame of the
1118      type in question. */
1119   if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
1120     /* Unknown protocol */
1121     if (update_col_info) {
1122       if (check_col(pinfo->cinfo, COL_INFO))
1123         col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
1124     }
1125     call_dissector(data_handle,next_tvb, pinfo, tree);
1126   }
1127   pinfo->fragmented = save_fragmented;
1128 }
1129
1130 #define ICMP_MIP_EXTENSION_PAD  0
1131 #define ICMP_MIP_MOB_AGENT_ADV  16
1132 #define ICMP_MIP_PREFIX_LENGTHS 19
1133 #define ICMP_MIP_CHALLENGE      24
1134
1135 static value_string mip_extensions[] = {
1136   { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"},  /* RFC 2002 */
1137   { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
1138                                                             /* RFC 2002 */
1139   { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"},   /* RFC 2002 */
1140   { ICMP_MIP_CHALLENGE, "Challenge Extension"},             /* RFC 3012 */
1141   { 0, NULL}
1142 };
1143
1144 /*
1145  * Dissect the mobile ip advertisement extensions.
1146  */
1147 static void
1148 dissect_mip_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
1149 {
1150   guint8       type;
1151   guint8       length;
1152   guint8       flags;
1153   proto_item   *ti;
1154   proto_tree   *mip_tree=NULL;
1155   proto_tree   *flags_tree=NULL;
1156   gint         numCOAs;
1157   gint         i;
1158
1159   /* Not much to do if we're not parsing everything */
1160   if (!tree) return;
1161   
1162   while (tvb_reported_length_remaining(tvb, offset) > 0) {
1163
1164         type = tvb_get_guint8(tvb, offset + 0);
1165         if (type)
1166           length = tvb_get_guint8(tvb, offset + 1);
1167         else
1168           length=0;
1169
1170         ti = proto_tree_add_text(tree, tvb, offset,
1171                                                          type?(length + 2):1,
1172                                                          "Ext: %s",
1173                                                          val_to_str(type, mip_extensions,
1174                                                                                 "Unknown ext %u"));
1175         mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
1176   
1177
1178         switch (type) {
1179         case ICMP_MIP_EXTENSION_PAD:
1180           /* One byte padding extension */
1181           /* Add our fields */
1182           /* type */
1183           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset, 
1184                                                   1, FALSE);
1185           offset++;
1186           break;
1187         case ICMP_MIP_MOB_AGENT_ADV:
1188           /* Mobility Agent Advertisement Extension (RFC 2002)*/
1189           /* Add our fields */
1190           /* type */
1191           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset, 
1192                                                   1, FALSE);
1193           offset++;
1194           /* length */
1195           proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset, 
1196                                                   1, FALSE);
1197           offset++;
1198           /* sequence number */
1199           proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset, 
1200                                                   2, FALSE);
1201           offset+=2;
1202           /* Registration Lifetime */
1203           proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset, 
1204                                                   2, FALSE);
1205           offset+=2;
1206           /* flags */
1207           flags = tvb_get_guint8(tvb, offset);
1208           ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
1209                                                            1, FALSE);
1210           flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
1211           proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
1212           proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
1213           proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
1214           proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
1215           proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
1216           proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
1217           proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
1218           proto_tree_add_boolean(flags_tree, hf_icmp_mip_res, tvb, offset, 1, flags);
1219           offset++;
1220           
1221           /* Reserved */
1222           proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset, 
1223                                                   1, FALSE);
1224           offset++;
1225           
1226           /* COAs */
1227           numCOAs = (length - 6) / 4;
1228           for (i=0; i<numCOAs; i++) {
1229                 proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset, 
1230                                                         4, FALSE);
1231                 offset+=4;
1232           }
1233           break;
1234         case ICMP_MIP_PREFIX_LENGTHS:
1235           /* Prefix-Lengths Extension  (RFC 2002)*/
1236           /* Add our fields */
1237           /* type */
1238           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset, 
1239                                                   1, FALSE);
1240           offset++;
1241           /* length */
1242           proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset, 
1243                                                   1, FALSE);
1244           offset++;
1245
1246           /* prefix lengths */
1247           for(i=0; i<length; i++) {
1248                 proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
1249                                                         1, FALSE);
1250                 offset++;
1251           }
1252           break;
1253         case ICMP_MIP_CHALLENGE:
1254           /* Challenge Extension  (RFC 3012)*/
1255           /* type */
1256           proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset, 
1257                                                   1, FALSE);
1258           offset++;
1259           /* length */
1260           proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset, 
1261                                                   1, FALSE);
1262           offset++;
1263           /* challenge */
1264           proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset, 
1265                                                   length, FALSE);
1266           offset+=length;
1267           
1268           break;
1269         default:
1270           g_warning("Unknown type(%u)!  I hope the length is right (%u)",
1271                                 type, length);
1272           offset += length;
1273           break;
1274         } /* switch type */
1275   } /* end while */
1276   
1277 } /* dissect_mip_extensions */
1278
1279 static const gchar *unreach_str[] = {"Network unreachable",
1280                                      "Host unreachable",
1281                                      "Protocol unreachable",
1282                                      "Port unreachable",
1283                                      "Fragmentation needed",
1284                                      "Source route failed",
1285                                      "Destination network unknown",
1286                                      "Destination host unknown",
1287                                      "Source host isolated",
1288                                      "Network administratively prohibited",
1289                                      "Host administratively prohibited",
1290                                      "Network unreachable for TOS",
1291                                      "Host unreachable for TOS",
1292                                      "Communication administratively filtered",
1293                                      "Host precedence violation",
1294                                      "Precedence cutoff in effect"};
1295                                      
1296 #define N_UNREACH       (sizeof unreach_str / sizeof unreach_str[0])
1297
1298 static const gchar *redir_str[] = {"Redirect for network",
1299                                    "Redirect for host",
1300                                    "Redirect for TOS and network",
1301                                    "Redirect for TOS and host"};
1302
1303 #define N_REDIRECT      (sizeof redir_str / sizeof redir_str[0])
1304
1305 static const gchar *ttl_str[] = {"TTL equals 0 during transit",
1306                                  "TTL equals 0 during reassembly"};
1307                                  
1308 #define N_TIMXCEED      (sizeof ttl_str / sizeof ttl_str[0])
1309
1310 static const gchar *par_str[] = {"IP header bad", "Required option missing"};
1311
1312 #define N_PARAMPROB     (sizeof par_str / sizeof par_str[0])
1313
1314 /*
1315  * RFC 792 for basic ICMP.
1316  * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
1317  * RFC 1256 for router discovery messages.
1318  * RFC 2002 and 3012 for Mobile IP stuff.
1319  */
1320 static void
1321 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1322 {
1323   proto_tree *icmp_tree;
1324   proto_item *ti;
1325   guint8     icmp_type;
1326   guint8     icmp_code;
1327   guint      length, reported_length;
1328   guint16    cksum, computed_cksum;
1329   gchar      type_str[64], code_str[64] = "";
1330   guint8     num_addrs = 0;
1331   guint8     addr_entry_size = 0;
1332   int        i;
1333   volatile address save_dl_src;
1334   volatile address save_dl_dst;
1335   volatile address save_net_src;
1336   volatile address save_net_dst;
1337   volatile address save_src;
1338   volatile address save_dst;
1339   gboolean   save_in_error_pkt;
1340   tvbuff_t   *next_tvb;
1341
1342   if (check_col(pinfo->cinfo, COL_PROTOCOL))
1343     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
1344   if (check_col(pinfo->cinfo, COL_INFO))
1345     col_clear(pinfo->cinfo, COL_INFO);
1346
1347   /* To do: check for runts, errs, etc. */
1348   icmp_type = tvb_get_guint8(tvb, 0);
1349   icmp_code = tvb_get_guint8(tvb, 1);
1350   cksum = tvb_get_ntohs(tvb, 2);
1351
1352   switch (icmp_type) {
1353     case ICMP_ECHOREPLY:
1354       strcpy(type_str, "Echo (ping) reply");
1355       break;
1356     case ICMP_UNREACH:
1357       strcpy(type_str, "Destination unreachable");
1358       if (icmp_code < N_UNREACH) {
1359         sprintf(code_str, "(%s)", unreach_str[icmp_code]);
1360       } else {
1361         strcpy(code_str, "(Unknown - error?)");
1362       }
1363       break;
1364     case ICMP_SOURCEQUENCH:
1365       strcpy(type_str, "Source quench (flow control)");
1366       break;
1367     case ICMP_REDIRECT:
1368       strcpy(type_str, "Redirect");
1369       if (icmp_code < N_REDIRECT) {
1370         sprintf(code_str, "(%s)", redir_str[icmp_code]);
1371       } else {
1372         strcpy(code_str, "(Unknown - error?)");
1373       }
1374       break;
1375     case ICMP_ECHO:
1376       strcpy(type_str, "Echo (ping) request");
1377       break;
1378     case ICMP_RTRADVERT:
1379       switch (icmp_code) {
1380       case 16: /* Mobile-Ip */
1381         strcpy(type_str, "Mobile IP Advertisement");
1382         break;
1383       default:
1384         strcpy(type_str, "Router advertisement");
1385         break;
1386       } /* switch icmp_code */
1387       break;
1388     case ICMP_RTRSOLICIT:
1389       strcpy(type_str, "Router solicitation");
1390       break;
1391     case ICMP_TIMXCEED:
1392       strcpy(type_str, "Time-to-live exceeded");
1393       if (icmp_code < N_TIMXCEED) {
1394         sprintf(code_str, "(%s)", ttl_str[icmp_code]);
1395       } else {
1396         strcpy(code_str, "(Unknown - error?)");
1397       }
1398       break;
1399     case ICMP_PARAMPROB:
1400       strcpy(type_str, "Parameter problem");
1401       if (icmp_code < N_PARAMPROB) {
1402         sprintf(code_str, "(%s)", par_str[icmp_code]);
1403       } else {
1404         strcpy(code_str, "(Unknown - error?)");
1405       }
1406       break;
1407     case ICMP_TSTAMP:
1408       strcpy(type_str, "Timestamp request");
1409       break;
1410     case ICMP_TSTAMPREPLY:
1411       strcpy(type_str, "Timestamp reply");
1412       break;
1413     case ICMP_IREQ:
1414       strcpy(type_str, "Information request");
1415       break;
1416     case ICMP_IREQREPLY:
1417       strcpy(type_str, "Information reply");
1418       break;
1419     case ICMP_MASKREQ:
1420       strcpy(type_str, "Address mask request");
1421       break;
1422     case ICMP_MASKREPLY:
1423       strcpy(type_str, "Address mask reply");
1424       break;
1425     default:
1426       strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
1427       break;
1428   }
1429
1430   if (check_col(pinfo->cinfo, COL_INFO))
1431     col_add_str(pinfo->cinfo, COL_INFO, type_str);
1432
1433   if (tree) {
1434     length = tvb_length(tvb);
1435     reported_length = tvb_reported_length(tvb);
1436     ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
1437     icmp_tree = proto_item_add_subtree(ti, ett_icmp);
1438     proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1, 
1439                                icmp_type,
1440                                "Type: %u (%s)",
1441                                icmp_type, type_str);
1442     proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1, 
1443                                icmp_code,
1444                                "Code: %u %s",
1445                                icmp_code, code_str);
1446
1447     if (!pinfo->fragmented && length >= reported_length) {
1448       /* The packet isn't part of a fragmented datagram and isn't
1449          truncated, so we can checksum it. */
1450
1451       computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
1452                                      reported_length);
1453       if (computed_cksum == 0) {
1454         proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1455                           cksum,
1456                           "Checksum: 0x%04x (correct)", cksum);
1457       } else {
1458         proto_tree_add_boolean_hidden(icmp_tree, hf_icmp_checksum_bad,
1459                           tvb, 2, 2, TRUE);
1460         proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
1461                   cksum,
1462                   "Checksum: 0x%04x (incorrect, should be 0x%04x)",
1463                   cksum, in_cksum_shouldbe(cksum, computed_cksum));
1464       }
1465     } else {
1466       proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
1467     }
1468
1469     /* Decode the second 4 bytes of the packet. */
1470     switch (icmp_type) {
1471       case ICMP_ECHOREPLY:
1472       case ICMP_ECHO:
1473       case ICMP_TSTAMP:
1474       case ICMP_TSTAMPREPLY:
1475       case ICMP_IREQ:
1476       case ICMP_IREQREPLY:
1477       case ICMP_MASKREQ:
1478       case ICMP_MASKREPLY:
1479         proto_tree_add_text(icmp_tree, tvb, 4, 2, "Identifier: 0x%04x",
1480           tvb_get_ntohs(tvb, 4));
1481         proto_tree_add_text(icmp_tree, tvb, 6, 2, "Sequence number: %02x:%02x",
1482           tvb_get_guint8(tvb, 6), tvb_get_guint8(tvb, 7));
1483         break;
1484
1485       case ICMP_UNREACH:
1486         switch (icmp_code) {
1487           case ICMP_FRAG_NEEDED:
1488             proto_tree_add_text(icmp_tree, tvb, 6, 2, "MTU of next hop: %u",
1489                   tvb_get_ntohs(tvb, 6));
1490             break;
1491         }
1492         break;
1493
1494       case ICMP_RTRADVERT:
1495         num_addrs = tvb_get_guint8(tvb, 4);
1496         proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
1497           num_addrs);
1498         addr_entry_size = tvb_get_guint8(tvb, 5);
1499         proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
1500           addr_entry_size);
1501         proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
1502           time_secs_to_str(tvb_get_ntohs(tvb, 6)));
1503         break;
1504
1505       case ICMP_PARAMPROB:
1506         proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
1507           tvb_get_guint8(tvb, 4));
1508         break;
1509
1510       case ICMP_REDIRECT:
1511         proto_tree_add_text(icmp_tree, tvb, 4, 4, "Gateway address: %s",
1512           ip_to_str(tvb_get_ptr(tvb, 4, 4)));
1513         break;
1514     }
1515
1516     /* Decode the additional information in the packet.  */
1517     switch (icmp_type) {
1518       case ICMP_UNREACH:
1519       case ICMP_TIMXCEED:
1520       case ICMP_PARAMPROB:
1521       case ICMP_SOURCEQUENCH:
1522       case ICMP_REDIRECT:
1523         /* Decode the IP header and first 64 bits of data from the
1524            original datagram.
1525
1526            Set the columns non-writable, so that the packet list
1527            shows this as an ICMP packet, not as the type of packet
1528            for which the ICMP packet was generated. */
1529         col_set_writable(pinfo->cinfo, FALSE);
1530
1531         /* Also, save the current values of the addresses, and restore
1532            them when we're finished dissecting the contained packet, so
1533            that the address columns in the summary don't reflect the
1534            contained packet, but reflect this packet instead. */
1535         save_dl_src = pinfo->dl_src;
1536         save_dl_dst = pinfo->dl_dst;
1537         save_net_src = pinfo->net_src;
1538         save_net_dst = pinfo->net_dst;
1539         save_src = pinfo->src;
1540         save_dst = pinfo->dst;
1541
1542         /* Save the current value of the "we're inside an error packet"
1543            flag, and set that flag; subdissectors may treat packets
1544            that are the payload of error packets differently from
1545            "real" packets. */
1546         save_in_error_pkt = pinfo->in_error_pkt;
1547         pinfo->in_error_pkt = TRUE;
1548
1549         /* Dissect the contained packet.
1550            Catch ReportedBoundsError, and do nothing if we see it,
1551            because it's not an error if the contained packet is short;
1552            there's no guarantee that all of it was included.
1553
1554            XXX - should catch BoundsError, and re-throw it after cleaning
1555            up. */
1556         next_tvb = tvb_new_subset(tvb, 8, -1, -1);
1557         TRY {
1558           call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
1559         }
1560         CATCH(ReportedBoundsError) {
1561           ; /* do nothing */
1562         }
1563         ENDTRY;
1564
1565         /* Restore the "we're inside an error packet" flag. */
1566         pinfo->in_error_pkt = save_in_error_pkt;
1567
1568         /* Restore the addresses. */
1569         pinfo->dl_src = save_dl_src;
1570         pinfo->dl_dst = save_dl_dst;
1571         pinfo->net_src = save_net_src;
1572         pinfo->net_dst = save_net_dst;
1573         pinfo->src = save_src;
1574         pinfo->dst = save_dst;
1575         break;
1576
1577       case ICMP_ECHOREPLY:
1578       case ICMP_ECHO:
1579         call_dissector(data_handle,tvb_new_subset(tvb, 8,-1,tvb_reported_length_remaining(tvb,8)), pinfo, icmp_tree);
1580         break;
1581
1582       case ICMP_RTRADVERT:
1583         if (addr_entry_size == 2) {
1584           for (i = 0; i < num_addrs; i++) {
1585             proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
1586               "Router address: %s",
1587               ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
1588             proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
1589               "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
1590           }
1591           if (icmp_code == 16) {
1592                 /* Mobile-Ip */
1593                 dissect_mip_extensions(tvb, 8 + i*8, icmp_tree);
1594           }
1595         } else
1596           call_dissector(data_handle,tvb_new_subset(tvb, 8,-1,tvb_reported_length_remaining(tvb,8)), pinfo, icmp_tree);
1597         break;
1598
1599       case ICMP_TSTAMP:
1600       case ICMP_TSTAMPREPLY:
1601         proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
1602           tvb_get_ntohl(tvb, 8));
1603         proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
1604           tvb_get_ntohl(tvb, 12));
1605         proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
1606           tvb_get_ntohl(tvb, 16));
1607         break;
1608
1609     case ICMP_MASKREQ:
1610     case ICMP_MASKREPLY:
1611         proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
1612           ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
1613         break;
1614     }
1615   }
1616 }
1617
1618 void
1619 proto_register_ip(void)
1620 {
1621         static hf_register_info hf[] = {
1622
1623                 { &hf_ip_version,
1624                 { "Version",            "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1625                         "", HFILL }},
1626
1627                 { &hf_ip_hdr_len,
1628                 { "Header Length",      "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
1629                         "", HFILL }},
1630
1631                 { &hf_ip_dsfield,
1632                 { "Differentiated Services field",      "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
1633                         "", HFILL }},
1634
1635                 { &hf_ip_dsfield_dscp,
1636                 { "Differentiated Services Codepoint",  "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
1637                         VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
1638                         "", HFILL }},
1639
1640                 { &hf_ip_dsfield_ect,
1641                 { "ECN-Capable Transport (ECT)",        "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
1642                         IPDSFIELD_ECT_MASK,
1643                         "", HFILL }},
1644
1645                 { &hf_ip_dsfield_ce,
1646                 { "ECN-CE",     "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
1647                         IPDSFIELD_CE_MASK,
1648                         "", HFILL }},
1649
1650                 { &hf_ip_tos,
1651                 { "Type of Service",    "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
1652                         "", HFILL }},
1653
1654                 { &hf_ip_tos_precedence,
1655                 { "Precedence",         "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
1656                         IPTOS_PREC_MASK,
1657                         "", HFILL }},
1658
1659                 { &hf_ip_tos_delay,
1660                 { "Delay",              "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
1661                         IPTOS_LOWDELAY,
1662                         "", HFILL }},
1663
1664                 { &hf_ip_tos_throughput,
1665                 { "Throughput",         "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
1666                         IPTOS_THROUGHPUT,
1667                         "", HFILL }},
1668
1669                 { &hf_ip_tos_reliability,
1670                 { "Reliability",        "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
1671                         IPTOS_RELIABILITY,
1672                         "", HFILL }},
1673
1674                 { &hf_ip_tos_cost,
1675                 { "Cost",               "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
1676                         IPTOS_LOWCOST,
1677                         "", HFILL }},
1678
1679                 { &hf_ip_len,
1680                 { "Total Length",       "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1681                         "", HFILL }},
1682
1683                 { &hf_ip_id,
1684                 { "Identification",     "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
1685                         "", HFILL }},
1686
1687                 { &hf_ip_dst,
1688                 { "Destination",        "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
1689                         "", HFILL }},
1690
1691                 { &hf_ip_src,
1692                 { "Source",             "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
1693                         "", HFILL }},
1694
1695                 { &hf_ip_addr,
1696                 { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
1697                         "", HFILL }},
1698
1699                 { &hf_ip_flags,
1700                 { "Flags",              "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1701                         "", HFILL }},
1702
1703                 { &hf_ip_flags_df,
1704                 { "Don't fragment",     "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF>>12,
1705                         "", HFILL }},
1706
1707                 { &hf_ip_flags_mf,
1708                 { "More fragments",     "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF>>12,
1709                         "", HFILL }},
1710
1711                 { &hf_ip_frag_offset,
1712                 { "Fragment offset",    "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
1713                         "", HFILL }},
1714
1715                 { &hf_ip_ttl,
1716                 { "Time to live",       "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1717                         "", HFILL }},
1718
1719                 { &hf_ip_proto,
1720                 { "Protocol",           "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
1721                         "", HFILL }},
1722
1723                 { &hf_ip_checksum,
1724                 { "Header checksum",    "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1725                         "", HFILL }},
1726
1727                 { &hf_ip_checksum_bad,
1728                 { "Bad Header checksum",        "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1729                         "", HFILL }},
1730
1731                 { &hf_ip_fragment_overlap,
1732                 { "Fragment overlap",   "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1733                         "Fragment overlaps with other fragments", HFILL }},
1734
1735                 { &hf_ip_fragment_overlap_conflict,
1736                 { "Conflicting data in fragment overlap",       "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1737                         "Overlapping fragments contained conflicting data", HFILL }},
1738
1739                 { &hf_ip_fragment_multiple_tails,
1740                 { "Multiple tail fragments found",      "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1741                         "Several tails were found when defragmenting the packet", HFILL }},
1742
1743                 { &hf_ip_fragment_too_long_fragment,
1744                 { "Fragment too long",  "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1745                         "Fragment contained data past end of packet", HFILL }},
1746
1747                 { &hf_ip_fragment_error,
1748                 { "Defragmentation error", "ip.fragment.error", FT_NONE, BASE_NONE, NULL, 0x0,
1749                         "Defragmentation error due to illegal fragments", HFILL }},
1750
1751                 { &hf_ip_fragment,
1752                 { "IP Fragment", "ip.fragment", FT_NONE, BASE_NONE, NULL, 0x0,
1753                         "IP Fragment", HFILL }},
1754
1755                 { &hf_ip_fragments,
1756                 { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
1757                         "IP Fragments", HFILL }},
1758         };
1759         static gint *ett[] = {
1760                 &ett_ip,
1761                 &ett_ip_dsfield,
1762                 &ett_ip_tos,
1763                 &ett_ip_off,
1764                 &ett_ip_options,
1765                 &ett_ip_option_sec,
1766                 &ett_ip_option_route,
1767                 &ett_ip_option_timestamp,
1768                 &ett_ip_fragments,
1769                 &ett_ip_fragment,
1770         };
1771         module_t *ip_module;
1772
1773         proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
1774         proto_register_field_array(proto_ip, hf, array_length(hf));
1775         proto_register_subtree_array(ett, array_length(ett));
1776
1777         /* subdissector code */
1778         ip_dissector_table = register_dissector_table("ip.proto",
1779             "IP protocol", FT_UINT8, BASE_DEC);
1780
1781         /* Register configuration options */
1782         ip_module = prefs_register_protocol(proto_ip, NULL);
1783         prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
1784             "Decode IPv4 TOS field as DiffServ field",
1785             "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
1786             &g_ip_dscp_actif);
1787         prefs_register_bool_preference(ip_module, "defragment",
1788                 "Reassemble fragmented IP datagrams",
1789                 "Whether fragmented IP datagrams should be reassembled",
1790                 &ip_defragment);
1791         prefs_register_bool_preference(ip_module, "ip_summary_in_tree",
1792             "Show IP summary in protocol tree",
1793             "Whether the IP summary line should be shown in the protocol tree",
1794             &ip_summary_in_tree);
1795
1796         register_dissector("ip", dissect_ip, proto_ip);
1797         register_init_routine(ip_defragment_init);
1798 }
1799
1800 void
1801 proto_reg_handoff_ip(void)
1802 {
1803         dissector_handle_t ip_handle;
1804
1805         data_handle = find_dissector("data");
1806         ip_handle = find_dissector("ip");
1807         dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
1808         dissector_add("ppp.protocol", PPP_IP, ip_handle);
1809         dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
1810         dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
1811         dissector_add("gre.proto", GRE_WCCP, ip_handle);
1812         dissector_add("llc.dsap", SAP_IP, ip_handle);
1813         dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
1814         dissector_add("null.type", BSD_AF_INET, ip_handle);
1815         dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
1816         dissector_add("fr.ietf", NLPID_IP, ip_handle);
1817         dissector_add("x.25.spi", NLPID_IP, ip_handle);
1818 }
1819
1820 void
1821 proto_register_icmp(void)
1822 {
1823   static hf_register_info hf[] = {
1824     
1825     { &hf_icmp_type,
1826       { "Type",         "icmp.type",            FT_UINT8, BASE_DEC,     NULL, 0x0,
1827         "", HFILL }},
1828
1829     { &hf_icmp_code,
1830       { "Code",         "icmp.code",            FT_UINT8, BASE_HEX,     NULL, 0x0,
1831         "", HFILL }},    
1832
1833     { &hf_icmp_checksum,
1834       { "Checksum",     "icmp.checksum",        FT_UINT16, BASE_HEX,    NULL, 0x0,
1835         "", HFILL }},
1836
1837     { &hf_icmp_checksum_bad,
1838       { "Bad Checksum", "icmp.checksum_bad",    FT_BOOLEAN, BASE_NONE,  NULL, 0x0,
1839         "", HFILL }},
1840
1841     { &hf_icmp_mip_type,
1842       { "Extension Type", "icmp.mip.type",      FT_UINT8, BASE_DEC,
1843         VALS(mip_extensions), 0x0,"", HFILL}},
1844
1845     { &hf_icmp_mip_length,
1846       { "Length", "icmp.mip.length",            FT_UINT8, BASE_DEC, NULL, 0x0,
1847         "", HFILL}},
1848
1849     { &hf_icmp_mip_prefix_length,
1850       { "Prefix Length", "icmp.mip.prefixlength",  FT_UINT8, BASE_DEC, NULL, 0x0,
1851         "", HFILL}},
1852
1853     { &hf_icmp_mip_seq,
1854       { "Sequence Number", "icmp.mip.seq",      FT_UINT16, BASE_DEC, NULL, 0x0,
1855         "", HFILL}},
1856
1857     { &hf_icmp_mip_life,
1858       { "Registration Lifetime", "icmp.mip.life",  FT_UINT16, BASE_DEC, NULL, 0x0,
1859         "", HFILL}},
1860
1861     { &hf_icmp_mip_flags,
1862       { "Flags", "icmp.mip.flags",            FT_UINT8, BASE_HEX, NULL, 0x0,
1863         "", HFILL}},
1864
1865     { &hf_icmp_mip_r,
1866       { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
1867         "Registration with this FA is required", HFILL }},
1868
1869     { &hf_icmp_mip_b,
1870       { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
1871         "This FA will not accept requests at this time", HFILL }},
1872
1873     { &hf_icmp_mip_h,
1874       { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
1875         "Home Agent Services Offered", HFILL }},
1876
1877     { &hf_icmp_mip_f,
1878       { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
1879         "Foreign Agent Services Offered", HFILL }},
1880
1881     { &hf_icmp_mip_m,
1882       { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
1883         "Minimal encapsulation tunneled datagram support", HFILL }},
1884
1885     { &hf_icmp_mip_g,
1886       { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
1887         "GRE encapsulated tunneled datagram support", HFILL }},
1888
1889     { &hf_icmp_mip_v,
1890       { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
1891         "Van Jacobson Header Compression Support", HFILL }},
1892
1893     { &hf_icmp_mip_res,
1894       { "Reserved", "icmp.mip.res", FT_BOOLEAN, 8, NULL, 1,
1895         "Reserved", HFILL }},
1896
1897     { &hf_icmp_mip_reserved,
1898       { "Reserved", "icmp.mip.reserved",     FT_UINT8, BASE_HEX, NULL, 0x0,
1899         "", HFILL}},
1900
1901     { &hf_icmp_mip_coa,
1902       { "Care-Of-Address", "icmp.mip.coa",    FT_IPv4, BASE_NONE, NULL, 0x0,
1903         "", HFILL}},
1904
1905     { &hf_icmp_mip_challenge,
1906       { "Challenge", "icmp.mip.challenge",    FT_BYTES, BASE_NONE, NULL, 0x0,
1907         "", HFILL}},
1908   };
1909   static gint *ett[] = {
1910     &ett_icmp,
1911         &ett_icmp_mip,
1912         &ett_icmp_mip_flags
1913   };
1914   
1915   proto_icmp = proto_register_protocol("Internet Control Message Protocol", 
1916                                        "ICMP", "icmp");
1917   proto_register_field_array(proto_icmp, hf, array_length(hf));
1918   proto_register_subtree_array(ett, array_length(ett));
1919 }
1920
1921 void
1922 proto_reg_handoff_icmp(void)
1923 {
1924   dissector_handle_t icmp_handle;
1925
1926   /*
1927    * Get handle for the IP dissector.
1928    */
1929   ip_handle = find_dissector("ip");
1930
1931   icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
1932   dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);
1933 }