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