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