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