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