9844fffe62c81a412acd03b710160c14d9d0dd55
[obnox/wireshark/wip.git] / packet-ospf.c
1 /* packet-ospf.c
2  * Routines for OSPF packet disassembly
3  * (c) Copyright Hannes R. Boehm <hannes@boehm.org>
4  *
5  * $Id: packet-ospf.c,v 1.68 2002/05/30 05:26:05 guy Exp $
6  *
7  * At this time, this module is able to analyze OSPF
8  * packets as specified in RFC2328. MOSPF (RFC1584) and other
9  * OSPF Extensions which introduce new Packet types
10  * (e.g the External Atributes LSA) are not supported.
11  * Furthermore RFC2740 (OSPFv3 - OSPF for IPv6) is now supported
12  *   - (c) 2001 Palle Lyckegaard <palle[AT]lyckegaard.dk>
13  *
14  * TOS - support is not fully implemented
15  * 
16  * Ethereal - Network traffic analyzer
17  * By Gerald Combs <gerald@ethereal.com>
18  * Copyright 1998 Gerald Combs
19  * 
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  * 
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  * 
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
33  */
34  
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
41 #endif
42
43 #ifdef HAVE_NETINET_IN_H
44 # include <netinet/in.h>
45 #endif
46
47 #include <stdio.h>
48 #include <string.h>
49
50 #include <glib.h>
51 #include <epan/packet.h>
52 #include "ipproto.h"
53 #include "in_cksum.h"
54 #include "packet-rsvp.h"
55
56 #define OSPF_VERSION_2 2
57 #define OSPF_VERSION_3 3
58 #define OSPF_VERSION_2_HEADER_LENGTH    24
59 #define OSPF_VERSION_3_HEADER_LENGTH    16
60
61
62 #define OSPF_HELLO      1
63 #define OSPF_DB_DESC    2
64 #define OSPF_LS_REQ     3
65 #define OSPF_LS_UPD     4
66 #define OSPF_LS_ACK     5
67
68 static const value_string pt_vals[] = {
69         {OSPF_HELLO,   "Hello Packet"   },
70         {OSPF_DB_DESC, "DB Descr."      },
71         {OSPF_LS_REQ,  "LS Request"     },
72         {OSPF_LS_UPD,  "LS Update"      },
73         {OSPF_LS_ACK,  "LS Acknowledge" },
74         {0,             NULL            }
75 };
76
77 #define OSPF_AUTH_NONE          0
78 #define OSPF_AUTH_SIMPLE        1
79 #define OSPF_AUTH_CRYPT         2
80
81 static const value_string auth_vals[] = {
82         {OSPF_AUTH_NONE,   "Null"            },
83         {OSPF_AUTH_SIMPLE, "Simple password" },
84         {OSPF_AUTH_CRYPT,  "Cryptographic"   },
85         {0,                NULL              }
86 };
87
88 #define OSPF_V2_OPTIONS_E               0x02
89 #define OSPF_V2_OPTIONS_MC              0x04
90 #define OSPF_V2_OPTIONS_NP              0x08
91 #define OSPF_V2_OPTIONS_EA              0x10
92 #define OSPF_V2_OPTIONS_DC              0x20
93 #define OSPF_V2_OPTIONS_O               0x40
94 #define OSPF_V2_OPTIONS_DN              0x01
95 #define OSPF_V3_OPTIONS_V6              0x01    
96 #define OSPF_V3_OPTIONS_E               0x02
97 #define OSPF_V3_OPTIONS_MC              0x04
98 #define OSPF_V3_OPTIONS_N               0x08
99 #define OSPF_V3_OPTIONS_R               0x10
100 #define OSPF_V3_OPTIONS_DC              0x20
101
102
103 #define OSPF_DBD_FLAG_MS        1
104 #define OSPF_DBD_FLAG_M         2
105 #define OSPF_DBD_FLAG_I         4
106
107 #define OSPF_LS_REQ_LENGTH      12
108
109 #define OSPF_LSTYPE_ROUTER      1
110 #define OSPF_LSTYPE_NETWORK     2
111 #define OSPF_LSTYPE_SUMMERY     3
112 #define OSPF_LSTYPE_ASBR        4
113 #define OSPF_LSTYPE_ASEXT       5
114 #define OSPF_LSTYPE_GRPMEMBER   6
115 #define OSPF_LSTYPE_ASEXT7      7
116 #define OSPF_LSTYPE_EXTATTR     8
117 #define OSPF_V3_LSTYPE_ROUTER                0x2001
118 #define OSPF_V3_LSTYPE_NETWORK               0x2002
119 #define OSPF_V3_LSTYPE_INTER_AREA_PREFIX     0x2003
120 #define OSPF_V3_LSTYPE_INTER_AREA_ROUTER     0x2004
121 #define OSPF_V3_LSTYPE_AS_EXTERNAL           0x4005
122 #define OSPF_V3_LSTYPE_GROUP_MEMBERSHIP      0x2006     
123 #define OSPF_V3_LSTYPE_TYPE_7                0x2007
124 #define OSPF_V3_LSTYPE_LINK                  0x0008
125 #define OSPF_V3_LSTYPE_INTRA_AREA_PREFIX     0x2009
126
127 /* Opaque LSA types */
128 #define OSPF_LSTYPE_OP_LINKLOCAL 9
129 #define OSPF_LSTYPE_OP_AREALOCAL 10
130 #define OSPF_LSTYPE_OP_ASWIDE    11
131
132 #define OSPF_LINK_PTP           1
133 #define OSPF_LINK_TRANSIT       2
134 #define OSPF_LINK_STUB          3
135 #define OSPF_LINK_VIRTUAL       4
136
137 #define OSPF_V3_LINK_PTP        1
138 #define OSPF_V3_LINK_TRANSIT    2
139 #define OSPF_V3_LINK_RESERVED   3
140 #define OSPF_V3_LINK_VIRTUAL    4
141
142 #define OSPF_LSA_HEADER_LENGTH  20
143
144 /* Known opaque LSAs */
145 #define OSPF_LSA_MPLS_TE        1
146
147
148 static const value_string ls_type_vals[] = {
149         {OSPF_LSTYPE_ROUTER,                  "Router-LSA"                   },
150         {OSPF_LSTYPE_NETWORK,                 "Network-LSA"                  },
151         {OSPF_LSTYPE_SUMMERY,                 "Summary-LSA (IP network)"     },
152         {OSPF_LSTYPE_ASBR,                    "Summary-LSA (ASBR)"           },
153         {OSPF_LSTYPE_ASEXT,                   "AS-External-LSA (ASBR)"       },
154         {OSPF_LSTYPE_GRPMEMBER,               "Group Membership LSA"         },
155         {OSPF_LSTYPE_ASEXT7,                  "NSSA AS-External-LSA"         },
156         {OSPF_LSTYPE_EXTATTR,                 "External Attributes LSA"      },
157         {OSPF_LSTYPE_OP_LINKLOCAL,            "Opaque LSA, Link-local scope" },
158         {OSPF_LSTYPE_OP_AREALOCAL,            "Opaque LSA, Area-local scope" },
159         {0,                                   NULL                           }
160
161 };
162
163 static const value_string ls_opaque_type_vals[] = {
164         {OSPF_LSA_MPLS_TE, "Traffic Engineering LSA"                },
165         {2,                "Sycamore Optical Topology Descriptions" },
166         {3,                "grace-LSA"                              },
167         {0,                NULL                                     }
168 };
169
170 static const value_string v3_ls_type_vals[] = {
171         {OSPF_V3_LSTYPE_ROUTER,               "Router-LSA"                   }, 
172         {OSPF_V3_LSTYPE_NETWORK,              "Network-LSA"                  }, 
173         {OSPF_V3_LSTYPE_INTER_AREA_PREFIX,    "Inter-Area-Prefix-LSA"        }, 
174         {OSPF_V3_LSTYPE_INTER_AREA_ROUTER,    "Inter-Area-Router-LSA"        }, 
175         {OSPF_V3_LSTYPE_AS_EXTERNAL,          "AS-External-LSA"              }, 
176         {OSPF_V3_LSTYPE_GROUP_MEMBERSHIP,     "Group-Membership-LSA"         }, 
177         {OSPF_V3_LSTYPE_TYPE_7,               "Type-LSA"                     }, 
178         {OSPF_V3_LSTYPE_LINK,                 "Link-LSA"                     },
179         {OSPF_V3_LSTYPE_INTRA_AREA_PREFIX,    "Intra-Area-Prefix-LSA"        },
180         {0,                                   NULL                           }
181
182 };
183
184
185 #define OSPF_V3_ROUTER_LSA_FLAG_B 0x01
186 #define OSPF_V3_ROUTER_LSA_FLAG_E 0x02
187 #define OSPF_V3_ROUTER_LSA_FLAG_V 0x04
188 #define OSPF_V3_ROUTER_LSA_FLAG_W 0x08
189
190 #define OSPF_V3_PREFIX_OPTION_NU 0x01
191 #define OSPF_V3_PREFIX_OPTION_LA 0x02
192 #define OSPF_V3_PREFIX_OPTION_MC 0x04
193 #define OSPF_V3_PREFIX_OPTION_P  0x08
194
195 #define OSPF_V3_AS_EXTERNAL_FLAG_T 0x01
196 #define OSPF_V3_AS_EXTERNAL_FLAG_F 0x02
197 #define OSPF_V3_AS_EXTERNAL_FLAG_E 0x04
198
199
200 static int proto_ospf = -1;
201
202 static gint ett_ospf = -1;
203 static gint ett_ospf_hdr = -1;
204 static gint ett_ospf_hello = -1;
205 static gint ett_ospf_desc = -1;
206 static gint ett_ospf_lsr = -1;
207 static gint ett_ospf_lsa = -1;
208 static gint ett_ospf_lsa_upd = -1;
209
210 /* Trees for opaque LSAs */
211 static gint ett_ospf_lsa_mpls = -1;
212 static gint ett_ospf_lsa_mpls_router = -1;
213 static gint ett_ospf_lsa_mpls_link = -1;
214 static gint ett_ospf_lsa_mpls_link_stlv = -1;
215
216 /*-----------------------------------------------------------------------
217  * OSPF Filtering
218  *-----------------------------------------------------------------------*/
219
220 /* The OSPF filtering keys */
221 enum {
222
223     OSPFF_MSG_TYPE,
224
225     OSPFF_MSG_MIN,
226     OSPFF_MSG_HELLO,
227     OSPFF_MSG_DB_DESC,
228     OSPFF_MSG_LS_REQ,
229     OSPFF_MSG_LS_UPD,
230     OSPFF_MSG_LS_ACK,
231     
232     OSPFF_LS_TYPE,
233     OSPFF_LS_OPAQUE_TYPE,
234
235     OSPFF_LS_MPLS_TE_INSTANCE,
236
237     OSPFF_LS_MIN,
238     OSPFF_LS_ROUTER,
239     OSPFF_LS_NETWORK,
240     OSPFF_LS_SUMMARY,
241     OSPFF_LS_ASBR,
242     OSPFF_LS_ASEXT,
243     OSPFF_LS_GRPMEMBER,
244     OSPFF_LS_ASEXT7,
245     OSPFF_LS_EXTATTR,
246     OSPFF_LS_OPAQUE,
247
248     OSPFF_SRC_ROUTER,
249     OSPFF_ADV_ROUTER,
250     OSPFF_LS_MPLS,
251     OSPFF_LS_MPLS_ROUTERID,
252
253     OSPFF_LS_MPLS_LINKID,
254     OSPFF_LS_MPLS_LOCAL_ADDR,
255     OSPFF_LS_MPLS_REMOTE_ADDR,
256     OSPFF_LS_MPLS_LOCAL_IFID,
257     OSPFF_LS_MPLS_REMOTE_IFID,
258
259     OSPFF_MAX
260 };
261
262 static int ospf_filter[OSPFF_MAX];
263
264 static hf_register_info ospff_info[] = {
265
266     /* Message type number */
267     {&ospf_filter[OSPFF_MSG_TYPE], 
268      { "Message Type", "ospf.msg", FT_UINT8, BASE_DEC, VALS(pt_vals), 0x0,
269         "", HFILL }},
270
271     /* Message types */
272     {&ospf_filter[OSPFF_MSG_HELLO], 
273      { "Hello", "ospf.msg.hello", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
274         "", HFILL }},
275     {&ospf_filter[OSPFF_MSG_DB_DESC], 
276      { "Database Description", "ospf.msg.dbdesc", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
277         "", HFILL }},
278     {&ospf_filter[OSPFF_MSG_LS_REQ], 
279      { "Link State Adv Request", "ospf.msg.lsreq", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
280         "", HFILL }},
281     {&ospf_filter[OSPFF_MSG_LS_UPD], 
282      { "Link State Adv Update", "ospf.msg.lsupdate", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
283         "", HFILL }},
284     {&ospf_filter[OSPFF_MSG_LS_ACK], 
285      { "Link State Adv Acknowledgement", "ospf.msg.lsack", FT_BOOLEAN, 
286        BASE_NONE, NULL, 0x0, "", HFILL }},
287
288
289
290     /* LS Types */
291     {&ospf_filter[OSPFF_LS_TYPE], 
292      { "Link-State Advertisement Type", "ospf.lsa", FT_UINT8, BASE_DEC, 
293        VALS(ls_type_vals), 0x0, "", HFILL }},
294     {&ospf_filter[OSPFF_LS_OPAQUE_TYPE], 
295      { "Link State ID Opaque Type", "ospf.lsid_opaque_type", FT_UINT8, BASE_DEC, 
296        VALS(ls_opaque_type_vals), 0x0, "", HFILL }},
297
298     {&ospf_filter[OSPFF_LS_MPLS_TE_INSTANCE], 
299      { "Link State ID TE-LSA Instance", "ospf.lsid_te_lsa.instance", FT_UINT16, BASE_DEC, 
300        NULL, 0x0, "", HFILL }},
301
302     {&ospf_filter[OSPFF_LS_ROUTER], 
303      { "Router LSA", "ospf.lsa.router", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
304         "", HFILL }},
305     {&ospf_filter[OSPFF_LS_NETWORK], 
306      { "Network LSA", "ospf.lsa.network", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
307         "", HFILL }},
308     {&ospf_filter[OSPFF_LS_SUMMARY], 
309      { "Summary LSA (IP Network)", "ospf.lsa.summary", FT_BOOLEAN, BASE_NONE, 
310        NULL, 0x0, "", HFILL }},
311     {&ospf_filter[OSPFF_LS_ASBR], 
312      { "Summary LSA (ASBR)", "ospf.lsa.asbr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
313         "", HFILL }},
314     {&ospf_filter[OSPFF_LS_ASEXT], 
315      { "AS-External LSA (ASBR)", "ospf.lsa.asext", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
316         "", HFILL }},
317     {&ospf_filter[OSPFF_LS_GRPMEMBER], 
318      { "Group Membership LSA", "ospf.lsa.member", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
319         "", HFILL }},
320     {&ospf_filter[OSPFF_LS_ASEXT7], 
321      { "NSSA AS-External LSA", "ospf.lsa.nssa", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
322         "", HFILL }},
323     {&ospf_filter[OSPFF_LS_EXTATTR], 
324      { "External Attributes LSA", "ospf.lsa.attr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
325         "", HFILL }},
326     {&ospf_filter[OSPFF_LS_OPAQUE], 
327      { "Opaque LSA", "ospf.lsa.opaque", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
328         "", HFILL }},
329
330     /* Other interesting OSPF values */
331
332     {&ospf_filter[OSPFF_SRC_ROUTER], 
333      { "Source OSPF Router", "ospf.srcrouter", FT_IPv4, BASE_NONE, NULL, 0x0, 
334        "", HFILL }}, 
335
336     {&ospf_filter[OSPFF_ADV_ROUTER], 
337      { "Advertising Router", "ospf.advrouter", FT_IPv4, BASE_NONE, NULL, 0x0, 
338        "", HFILL }}, 
339
340    {&ospf_filter[OSPFF_LS_MPLS], 
341      { "MPLS Traffic Engineering LSA", "ospf.lsa.mpls", FT_BOOLEAN, 
342        BASE_NONE, NULL, 0x0, "", HFILL }},
343
344     {&ospf_filter[OSPFF_LS_MPLS_ROUTERID], 
345      { "MPLS/TE Router ID", "ospf.mpls.routerid", FT_IPv4, BASE_NONE, NULL, 0x0, 
346        "", HFILL }},
347
348     {&ospf_filter[OSPFF_LS_MPLS_LINKID], 
349      { "MPLS/TE Link ID", "ospf.mpls.linkid", FT_IPv4, BASE_NONE, NULL, 0x0, 
350        "", HFILL }},
351     {&ospf_filter[OSPFF_LS_MPLS_LOCAL_ADDR], 
352      { "MPLS/TE Local Interface Address", "ospf.mpls.local_addr", FT_IPv4, 
353        BASE_NONE, NULL, 0x0, "", HFILL }},
354     {&ospf_filter[OSPFF_LS_MPLS_REMOTE_ADDR], 
355      { "MPLS/TE Remote Interface Address", "ospf.mpls.remote_addr", FT_IPv4, 
356        BASE_NONE, NULL, 0x0, "", HFILL }},
357     {&ospf_filter[OSPFF_LS_MPLS_LOCAL_IFID], 
358      { "MPLS/TE Local Interface Index", "ospf.mpls.local_id", FT_UINT32, 
359        BASE_DEC, NULL, 0x0, "", HFILL }},
360     {&ospf_filter[OSPFF_LS_MPLS_REMOTE_IFID], 
361      { "MPLS/TE Remote Interface Index", "ospf.mpls.remote_id", FT_UINT32, 
362        BASE_DEC, NULL, 0x0, "", HFILL }},
363
364
365
366 };
367
368 static guint8 ospf_msg_type_to_filter (guint8 msg_type)
369 {
370     if (msg_type >= OSPF_HELLO && 
371         msg_type <= OSPF_LS_ACK) 
372         return msg_type + OSPFF_MSG_MIN;
373     return -1;
374 }
375
376 static guint8 ospf_ls_type_to_filter (guint8 ls_type)
377 {
378     if (ls_type >= OSPF_LSTYPE_ROUTER && 
379         ls_type <= OSPF_LSTYPE_EXTATTR) 
380         return OSPFF_LS_MIN + ls_type;
381     else if (ls_type >= OSPF_LSTYPE_OP_LINKLOCAL && 
382              ls_type <= OSPF_LSTYPE_OP_ASWIDE)
383         return OSPFF_LS_OPAQUE;
384     else
385         return -1;
386 }
387
388 static dissector_handle_t data_handle;
389
390 static void dissect_ospf_hello(tvbuff_t*, int, proto_tree*, guint8);
391 static void dissect_ospf_db_desc(tvbuff_t*, int, proto_tree*, guint8); 
392 static void dissect_ospf_ls_req(tvbuff_t*, int, proto_tree*, guint8); 
393 static void dissect_ospf_ls_upd(tvbuff_t*, int, proto_tree*, guint8); 
394 static void dissect_ospf_ls_ack(tvbuff_t*, int, proto_tree*, guint8); 
395
396 /* dissect_ospf_v[23]lsa returns the offset of the next LSA
397  * if disassemble_body is set to FALSE (e.g. in LSA ACK 
398  * packets), the offset is set to the offset of the next
399  * LSA header
400  */
401 static int dissect_ospf_v2_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body); 
402 static int dissect_ospf_v3_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body); 
403
404 static void dissect_ospf_options(tvbuff_t *, int, proto_tree *, guint8);
405
406 static void dissect_ospf_v3_prefix_options(tvbuff_t *, int, proto_tree *);
407
408 static void dissect_ospf_v3_address_prefix(tvbuff_t *, int, int, proto_tree *);
409
410 static void 
411 dissect_ospf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
412 {
413     proto_tree *ospf_tree = NULL;
414     proto_item *ti; 
415     proto_tree *ospf_header_tree;
416     guint8  version;
417     guint8  packet_type;
418     guint16 ospflen;
419     vec_t cksum_vec[4];
420     int cksum_vec_len;
421     guint32 phdr[2];
422     guint16 cksum, computed_cksum;
423     guint length, reported_length;
424     guint16 auth_type;
425     char auth_data[8];
426     int crypto_len;
427     unsigned int ospf_header_length;
428     guint8 instance_ID;
429     guint8 reserved;
430     guint32 areaid;
431
432
433     if (check_col(pinfo->cinfo, COL_PROTOCOL))
434         col_set_str(pinfo->cinfo, COL_PROTOCOL, "OSPF");
435     if (check_col(pinfo->cinfo, COL_INFO))
436         col_clear(pinfo->cinfo, COL_INFO);
437
438     version = tvb_get_guint8(tvb, 0);
439     switch (version) {
440         case OSPF_VERSION_2:
441             ospf_header_length = OSPF_VERSION_2_HEADER_LENGTH;
442             break;
443         case OSPF_VERSION_3:
444             ospf_header_length = OSPF_VERSION_3_HEADER_LENGTH;
445             break;
446         default:
447             ospf_header_length = 0;
448             break;
449     }
450
451     packet_type = tvb_get_guint8(tvb, 1);
452     if (check_col(pinfo->cinfo, COL_INFO)) {
453         col_add_str(pinfo->cinfo, COL_INFO,
454                     val_to_str(packet_type, pt_vals, "Unknown (%u)"));
455     }  
456
457     if (tree) {
458         ospflen = tvb_get_ntohs(tvb, 2);
459
460         ti = proto_tree_add_item(tree, proto_ospf, tvb, 0, ospflen, FALSE);
461         ospf_tree = proto_item_add_subtree(ti, ett_ospf);
462
463         ti = proto_tree_add_text(ospf_tree, tvb, 0, ospf_header_length,
464                                  "OSPF Header"); 
465         ospf_header_tree = proto_item_add_subtree(ti, ett_ospf_hdr);
466
467         proto_tree_add_text(ospf_header_tree, tvb, 0, 1, "OSPF Version: %u",
468                             version);  
469         proto_tree_add_item(ospf_header_tree, ospf_filter[OSPFF_MSG_TYPE], 
470                             tvb, 1, 1, FALSE);
471         proto_tree_add_item_hidden(ospf_header_tree, 
472                                    ospf_filter[ospf_msg_type_to_filter(packet_type)],
473                                    tvb, 1, 1, FALSE);
474         proto_tree_add_text(ospf_header_tree, tvb, 2, 2, "Packet Length: %u",
475                             ospflen);
476         proto_tree_add_item(ospf_header_tree, ospf_filter[OSPFF_SRC_ROUTER], 
477                             tvb, 4, 4, FALSE);
478         areaid=tvb_get_ntohl(tvb,8);
479         proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: %s%s",
480                                ip_to_str(tvb_get_ptr(tvb, 8, 4)), areaid == 0 ? " (Backbone)" : "");
481         cksum = tvb_get_ntohs(tvb, 12);
482         length = tvb_length(tvb);
483         /* XXX - include only the length from the OSPF header? */
484         reported_length = tvb_reported_length(tvb);
485         if (cksum == 0) {
486                 /* No checksum supplied in the packet. */
487                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
488                     "Packet Checksum: 0x%04x (none)", cksum);
489         } else if (!pinfo->fragmented && length >= reported_length
490                 && length >= ospf_header_length
491                 && (version == OSPF_VERSION_2 || version == OSPF_VERSION_3)) {
492             /* The packet isn't part of a fragmented datagram and isn't
493                truncated, and we know how to checksum this version of
494                OSPF, so we can checksum it. */
495
496             switch (version) {
497
498             case OSPF_VERSION_2:
499                 /* Header, not including the authentication data (the OSPFv2
500                    checksum excludes the 64-bit authentication field). */
501                 cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, 16);
502                 cksum_vec[0].len = 16;
503                 if (length > ospf_header_length) {
504                     /* Rest of the packet, again not including the
505                        authentication data. */
506                     reported_length -= ospf_header_length;
507                     cksum_vec[1].ptr = tvb_get_ptr(tvb, ospf_header_length, reported_length);
508                     cksum_vec[1].len = reported_length;
509                     cksum_vec_len = 2;
510                 } else {
511                     /* There's nothing but a header. */
512                     cksum_vec_len = 1;
513                 }
514                 break;
515
516             case OSPF_VERSION_3:
517                 /* IPv6-style checksum, covering the entire OSPF packet
518                    and a prepended IPv6 pseudo-header. */
519
520                 /* Set up the fields of the pseudo-header. */
521                 cksum_vec[0].ptr = pinfo->src.data;
522                 cksum_vec[0].len = pinfo->src.len;
523                 cksum_vec[1].ptr = pinfo->dst.data;
524                 cksum_vec[1].len = pinfo->dst.len;
525                 cksum_vec[2].ptr = (const guint8 *)&phdr;
526                 phdr[0] = htonl(ospflen);
527                 phdr[1] = htonl(IP_PROTO_OSPF);
528                 cksum_vec[2].len = 8;
529
530                 cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, reported_length);
531                 cksum_vec[3].len = reported_length;
532                 cksum_vec_len = 4;
533                 break;
534
535             default:
536                 g_assert_not_reached();
537                 cksum_vec_len = 0;
538             }
539             computed_cksum = in_cksum(cksum_vec, cksum_vec_len);
540             if (computed_cksum == 0) {
541                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
542                         "Packet Checksum: 0x%04x (correct)", cksum);
543             } else {
544                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
545                         "Packet Checksum: 0x%04x (incorrect, should be 0x%04x)",
546                         cksum, in_cksum_shouldbe(cksum, computed_cksum));
547             }
548         } else {
549             proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
550                 "Packet Checksum: 0x%04x", cksum);
551         }
552
553
554         /* Authentication is only valid for OSPFv2 */
555         if ( version == OSPF_VERSION_2 ) {        
556             auth_type = tvb_get_ntohs(tvb, 14);
557             proto_tree_add_text(ospf_header_tree, tvb, 14, 2, "Auth Type: %s",
558                             val_to_str(auth_type, auth_vals, "Unknown (%u)"));
559             switch (auth_type) {
560
561             case OSPF_AUTH_NONE:
562                 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (none)");
563                 break;
564
565             case OSPF_AUTH_SIMPLE:
566                 tvb_get_nstringz0(tvb, 16, 8, auth_data);
567                 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data: %s", auth_data);
568                 break;
569
570             case OSPF_AUTH_CRYPT:
571                 proto_tree_add_text(ospf_header_tree, tvb, 18, 1, "Auth Key ID: %u",
572                                 tvb_get_guint8(tvb, 18));
573                 crypto_len = tvb_get_guint8(tvb, 19);
574                 proto_tree_add_text(ospf_header_tree, tvb, 19, 1, "Auth Data Length: %u",
575                                 crypto_len);
576                 proto_tree_add_text(ospf_header_tree, tvb, 20, 4, "Auth Crypto Sequence Number: 0x%x",
577                                 tvb_get_ntohl(tvb, 20));
578   
579                 /* Show the message digest that was appended to the end of the
580                    OSPF message - but only if it's present (we don't want
581                    to get an exception before we've tried dissecting OSPF
582                    message). */
583                 if (tvb_bytes_exist(tvb, ospflen, crypto_len)) {
584                     proto_tree_add_text(ospf_header_tree, tvb, ospflen, crypto_len,
585                                     "Auth Data: %s",
586                                     tvb_bytes_to_str(tvb, ospflen, crypto_len));
587                 }
588                 break;
589
590             default:
591                 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (unknown)");
592                 break;
593             }
594
595         }
596
597         /* Instance ID and "reserved" is OSPFv3-only */
598         if ( version == OSPF_VERSION_3 ) {
599             instance_ID = tvb_get_guint8(tvb, 14);
600             proto_tree_add_text(ospf_header_tree, tvb, 14, 1, "Instance ID: %u",
601                             instance_ID);
602             reserved = tvb_get_guint8(tvb, 15);
603             proto_tree_add_text(ospf_header_tree, tvb, 15, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
604                                 reserved);
605
606         }
607
608         /* Adjust the length of the tvbuff to match the size of the OSPF
609          * packet (since the dissect routines use it to work out where the
610          * end of the OSPF packet is).
611          */
612         tvb_set_reported_length(tvb, ospflen);
613
614         switch (packet_type){
615
616         case OSPF_HELLO:
617             dissect_ospf_hello(tvb, ospf_header_length, ospf_tree, version);
618             break;
619
620         case OSPF_DB_DESC:
621             dissect_ospf_db_desc(tvb, ospf_header_length, ospf_tree, version);
622             break;
623
624         case OSPF_LS_REQ:
625             dissect_ospf_ls_req(tvb, ospf_header_length, ospf_tree, version);
626             break;
627
628         case OSPF_LS_UPD:
629             dissect_ospf_ls_upd(tvb, ospf_header_length, ospf_tree, version);
630             break;
631
632         case OSPF_LS_ACK:
633             dissect_ospf_ls_ack(tvb, ospf_header_length, ospf_tree, version);
634             break;
635
636         default:
637             call_dissector(data_handle,
638                 tvb_new_subset(tvb, ospf_header_length, -1, -1), pinfo, tree);
639             break;
640         }
641     }
642 }
643
644 static void
645 dissect_ospf_hello(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
646 {
647     proto_tree *ospf_hello_tree;
648     proto_item *ti; 
649
650     ti = proto_tree_add_text(tree, tvb, offset, -1, "OSPF Hello Packet");
651     ospf_hello_tree = proto_item_add_subtree(ti, ett_ospf_hello);
652     
653     switch (version ) {
654         case OSPF_VERSION_2:
655             proto_tree_add_text(ospf_hello_tree, tvb, offset, 4, "Network Mask: %s",
656                         ip_to_str(tvb_get_ptr(tvb, offset, 4)));
657             proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 2,
658                         "Hello Interval: %u seconds",
659                         tvb_get_ntohs(tvb, offset + 4));
660
661             dissect_ospf_options(tvb, offset + 6, ospf_hello_tree, version);
662             proto_tree_add_text(ospf_hello_tree, tvb, offset + 7, 1, "Router Priority: %u",
663                         tvb_get_guint8(tvb, offset + 7));
664             proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 4, "Router Dead Interval: %u seconds",
665                         tvb_get_ntohl(tvb, offset + 8));
666             proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
667                         ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
668             proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
669                         ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
670
671             offset += 20;
672             while (tvb_reported_length_remaining(tvb, offset) != 0) {
673                 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
674                             "Active Neighbor: %s",
675                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
676                 offset += 4;
677             }
678             break;
679         case OSPF_VERSION_3:
680             proto_tree_add_text(ospf_hello_tree, tvb, offset + 0, 4, "Interface ID: %u",
681                         tvb_get_ntohl(tvb, offset + 0));
682             proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 1, "Router Priority: %u",
683                         tvb_get_guint8(tvb, offset + 4));
684             dissect_ospf_options(tvb, offset + 5, ospf_hello_tree, version);
685             proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 2,
686                         "Hello Interval: %u seconds",
687                         tvb_get_ntohs(tvb, offset + 8));
688             proto_tree_add_text(ospf_hello_tree, tvb, offset + 10, 2, "Router Dead Interval: %u seconds",
689                         tvb_get_ntohs(tvb, offset + 10));
690             proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
691                         ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
692             proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
693                         ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
694             offset += 20;
695             while (tvb_reported_length_remaining(tvb, offset) != 0) {
696                 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
697                             "Active Neighbor: %s",
698                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
699                 offset += 4;
700             }
701
702             break;
703
704         default:    
705             break;
706     }
707 }
708
709 static void
710 dissect_ospf_db_desc(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
711 {
712     proto_tree *ospf_db_desc_tree=NULL;
713     proto_item *ti; 
714     guint8 flags;
715     guint8 reserved;
716     char flags_string[20] = "";
717
718     if (tree) {
719         ti = proto_tree_add_text(tree, tvb, offset, -1, "OSPF DB Description"); 
720         ospf_db_desc_tree = proto_item_add_subtree(ti, ett_ospf_desc);
721
722         switch (version ) {
723  
724             case OSPF_VERSION_2:
725
726                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 2, "Interface MTU: %u",
727                             tvb_get_ntohs(tvb, offset));
728
729                 dissect_ospf_options(tvb, offset + 2, ospf_db_desc_tree, version);
730
731                 flags = tvb_get_guint8(tvb, offset + 3);
732                 if (flags & OSPF_DBD_FLAG_MS)
733                     strcat(flags_string, "MS");
734                 if (flags & OSPF_DBD_FLAG_M) {
735                     if (flags_string[0] != '\0')
736                         strcat(flags_string, "/");
737                     strcat(flags_string, "M");
738                 }
739                 if (flags & OSPF_DBD_FLAG_I) {
740                     if (flags_string[0] != '\0')
741                         strcat(flags_string, "/");
742                     strcat(flags_string, "I");
743                 }
744                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 3, 1, "Flags: 0x%x (%s)",
745                             flags, flags_string);
746                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 4, "DD Sequence: %u",
747                             tvb_get_ntohl(tvb, offset + 4));
748
749                 offset += 8;
750                 break;
751
752             case OSPF_VERSION_3:
753
754                 reserved = tvb_get_guint8(tvb, offset);
755                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
756                                 reserved);
757
758                 dissect_ospf_options(tvb, offset + 1, ospf_db_desc_tree, version);
759
760                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 2, "Interface MTU: %u",
761                             tvb_get_ntohs(tvb, offset+4));
762
763                 reserved = tvb_get_guint8(tvb, offset + 6);
764                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 6, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
765                                 reserved);
766
767                 flags = tvb_get_guint8(tvb, offset + 7);
768                 if (flags & OSPF_DBD_FLAG_MS)
769                     strcat(flags_string, "MS");
770                 if (flags & OSPF_DBD_FLAG_M) {
771                     if (flags_string[0] != '\0')
772                         strcat(flags_string, "/");
773                     strcat(flags_string, "M");
774                 }
775                 if (flags & OSPF_DBD_FLAG_I) {
776                     if (flags_string[0] != '\0')
777                         strcat(flags_string, "/");
778                     strcat(flags_string, "I");
779                 }
780                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 7, 1, "Flags: 0x%x (%s)",
781                             flags, flags_string);
782
783                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 8, 4, "DD Sequence: %u",
784                             tvb_get_ntohl(tvb, offset + 8));
785
786                 offset += 12;
787                 break;
788
789             default:
790                 break;
791         }
792     }
793
794     /* LS Headers will be processed here */
795     /* skip to the end of DB-Desc header */
796     while (tvb_reported_length_remaining(tvb, offset) != 0) {
797       if ( version == OSPF_VERSION_2)
798           offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE);
799       else
800           if ( version == OSPF_VERSION_3)
801               offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE);
802     }
803
804 }
805
806 static void
807 dissect_ospf_ls_req(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
808 {
809     proto_tree *ospf_lsr_tree;
810     proto_item *ti;
811     guint32 ls_type;
812     guint8 reserved;
813
814     /* zero or more LS requests may be within a LS Request */
815     /* we place every request for a LSA in a single subtree */
816     while (tvb_reported_length_remaining(tvb, offset) != 0) {
817         ti = proto_tree_add_text(tree, tvb, offset, OSPF_LS_REQ_LENGTH,
818                                  "Link State Request"); 
819         ospf_lsr_tree = proto_item_add_subtree(ti, ett_ospf_lsr);
820       
821         switch ( version ) {
822
823             case OSPF_VERSION_2:
824                 ls_type = tvb_get_ntohl(tvb, offset);
825                 proto_tree_add_item(ospf_lsr_tree, ospf_filter[OSPFF_LS_TYPE], 
826                                     tvb, offset, 4, FALSE);
827                 break;
828             case OSPF_VERSION_3:
829                 reserved = tvb_get_ntohs(tvb, offset);
830                 proto_tree_add_text(ospf_lsr_tree, tvb, offset, 2,
831                     (reserved == 0 ? "Reserved: %u" :  "Reserved: %u (incorrect, should be 0)"), reserved);
832                 ls_type = tvb_get_ntohs(tvb, offset+2);
833                 proto_tree_add_text(ospf_lsr_tree, tvb, offset+2, 2, "LS Type: %s (0x%04x)",
834                             val_to_str(ls_type, v3_ls_type_vals, "Unknown"),
835                             ls_type);
836                   break;
837             default:
838                  ls_type=0;
839                  break;
840         }
841
842
843         proto_tree_add_text(ospf_lsr_tree, tvb, offset + 4, 4, "Link State ID: %s", 
844                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
845         proto_tree_add_item(ospf_lsr_tree, ospf_filter[OSPFF_ADV_ROUTER],
846                             tvb, offset + 8, 4, FALSE);
847
848         offset += 12;
849     }
850 }
851
852 static void
853 dissect_ospf_ls_upd(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
854 {
855     proto_tree *ospf_lsa_upd_tree=NULL;
856     proto_item *ti;
857     guint32 lsa_nr;
858     guint32 lsa_counter; 
859
860     ti = proto_tree_add_text(tree, tvb, offset, -1, "LS Update Packet");
861     ospf_lsa_upd_tree = proto_item_add_subtree(ti, ett_ospf_lsa_upd);
862
863     lsa_nr = tvb_get_ntohl(tvb, offset);
864     proto_tree_add_text(ospf_lsa_upd_tree, tvb, offset, 4, "Number of LSAs: %u",
865                         lsa_nr);
866     /* skip to the beginning of the first LSA */
867     offset += 4; /* the LS Upd Packet contains only a 32 bit #LSAs field */
868     
869     lsa_counter = 0;
870     while (lsa_counter < lsa_nr) {
871         if ( version == OSPF_VERSION_2)
872             offset = dissect_ospf_v2_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
873         else
874             if ( version == OSPF_VERSION_3)
875                 offset = dissect_ospf_v3_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
876         lsa_counter += 1;
877     }
878 }
879
880 static void
881 dissect_ospf_ls_ack(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
882 {
883     /* the body of a LS Ack packet simply contains zero or more LSA Headers */
884     while (tvb_reported_length_remaining(tvb, offset) != 0) {
885         if ( version == OSPF_VERSION_2)
886             offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE);
887         else
888             if ( version == OSPF_VERSION_3)
889               offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE);
890     }
891 }
892
893 /*
894  * Returns if an LSA is opaque, i.e. requires special treatment 
895  */
896 static int
897 is_opaque(int lsa_type)
898 {
899     return (lsa_type >= OSPF_LSTYPE_OP_LINKLOCAL &&
900         lsa_type <= OSPF_LSTYPE_OP_ASWIDE);
901 }
902
903 /* MPLS/TE TLV types */
904 #define MPLS_TLV_ROUTER    1
905 #define MPLS_TLV_LINK      2
906
907 /* MPLS/TE Link STLV types */
908 enum {
909     MPLS_LINK_TYPE       = 1,
910     MPLS_LINK_ID,
911     MPLS_LINK_LOCAL_IF,
912     MPLS_LINK_REMOTE_IF,
913     MPLS_LINK_TE_METRIC,
914     MPLS_LINK_MAX_BW,
915     MPLS_LINK_MAX_RES_BW,
916     MPLS_LINK_UNRES_BW,
917     MPLS_LINK_COLOR,
918     MPLS_LINK_LOCAL_ID = 11,
919     MPLS_LINK_REMOTE_ID,
920     MPLS_LINK_PROTECTION = 14,
921     MPLS_LINK_IF_SWITCHING_DESC,
922     MPLS_LINK_SHARED_RISK_GROUP,
923 };
924
925 static const value_string mpls_link_stlv_str[] = {
926     {MPLS_LINK_TYPE, "Link Type"},
927     {MPLS_LINK_ID, "Link ID"},
928     {MPLS_LINK_LOCAL_IF, "Local Interface IP Address"},
929     {MPLS_LINK_REMOTE_IF, "Remote Interface IP Address"},
930     {MPLS_LINK_TE_METRIC, "Traffic Engineering Metric"},
931     {MPLS_LINK_MAX_BW, "Maximum Bandwidth"},
932     {MPLS_LINK_MAX_RES_BW, "Maximum Reservable Bandwidth"},
933     {MPLS_LINK_UNRES_BW, "Unreserved Bandwidth"},
934     {MPLS_LINK_COLOR, "Resource Class/Color"},
935     {MPLS_LINK_LOCAL_ID, "Link Local Identifier"},
936     {MPLS_LINK_REMOTE_ID, "Link Remote Identifier"},
937     {MPLS_LINK_PROTECTION, "Link Protection Type"},
938     {MPLS_LINK_IF_SWITCHING_DESC, "Interface Switching Capability Descriptor"},
939     {MPLS_LINK_SHARED_RISK_GROUP, "Shared Risk Link Group"},
940     {0, NULL},
941 };
942
943 /* 
944  * Dissect MPLS/TE opaque LSA 
945  */
946 static void
947 dissect_ospf_lsa_mpls(tvbuff_t *tvb, int offset, proto_tree *tree,
948                       guint32 length)
949 {
950     proto_item *ti; 
951     proto_tree *mpls_tree;
952     proto_tree *tlv_tree;
953     proto_tree *stlv_tree;
954
955     int tlv_type;
956     int tlv_length;
957     int tlv_end_offset;
958
959     int stlv_type, stlv_len, stlv_offset;
960     char *stlv_name;
961     int i;
962
963     ti = proto_tree_add_text(tree, tvb, offset, length,
964                              "MPLS Traffic Engineering LSA");
965     proto_tree_add_item_hidden(tree, ospf_filter[OSPFF_LS_MPLS],
966                                tvb, offset, 2, FALSE);
967     mpls_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls);
968
969     while (length != 0) {
970         tlv_type = tvb_get_ntohs(tvb, offset);
971         tlv_length = tvb_get_ntohs(tvb, offset + 2);
972         tlv_end_offset = offset + tlv_length + 4;
973
974         switch (tlv_type) {
975
976         case MPLS_TLV_ROUTER:
977             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
978                                      "Router Address: %s", 
979                                      ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
980             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_router);
981             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 1 - Router Address");
982             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
983                                 tlv_length);
984             proto_tree_add_item(tlv_tree, ospf_filter[OSPFF_LS_MPLS_ROUTERID],
985                                 tvb, offset+4, 4, FALSE);
986             break;
987
988         case MPLS_TLV_LINK:
989             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
990                                      "Link Information");
991             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
992             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 2 - Link Information");
993             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
994                                 tlv_length);
995             stlv_offset = offset + 4;
996
997             /* Walk down the sub-TLVs for link information */
998             while (stlv_offset < tlv_end_offset) {
999                 stlv_type = tvb_get_ntohs(tvb, stlv_offset);
1000                 stlv_len = tvb_get_ntohs(tvb, stlv_offset + 2);
1001                 stlv_name = val_to_str(stlv_type, mpls_link_stlv_str, "Unknown sub-TLV");
1002                 switch (stlv_type) {
1003
1004                 case MPLS_LINK_TYPE:
1005                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1006                                              "%s: %u", stlv_name,
1007                                              tvb_get_guint8(tvb, stlv_offset + 4));
1008                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1009                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1010                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1011                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1012                                         stlv_len);
1013                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "%s: %u", stlv_name,
1014                                         tvb_get_guint8(tvb, stlv_offset + 4));
1015                     break;
1016
1017                 case MPLS_LINK_ID:
1018                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1019                                              "%s: %s (%x)", stlv_name,
1020                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)),
1021                                              tvb_get_ntohl(tvb, stlv_offset + 4));
1022                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1023                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1024                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1025                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1026                                         stlv_len);
1027                     proto_tree_add_item(stlv_tree, ospf_filter[OSPFF_LS_MPLS_LINKID],
1028                                         tvb, stlv_offset+4, 4, FALSE);
1029                     break;
1030
1031                 case MPLS_LINK_LOCAL_IF:
1032                 case MPLS_LINK_REMOTE_IF:
1033                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1034                                              "%s", stlv_name);
1035                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1036                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1037                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1038                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1039                                         stlv_len);
1040                     /*   The Local/Remote Interface IP Address sub-TLV is TLV type 3/4, and is 4N
1041                        octets in length, where N is the number of neighbor addresses. */
1042                     for (i=0; i < stlv_len; i+=4)
1043                       proto_tree_add_item(stlv_tree, 
1044                                           stlv_type==MPLS_LINK_LOCAL_IF ? 
1045                                           ospf_filter[OSPFF_LS_MPLS_LOCAL_ADDR] : 
1046                                           ospf_filter[OSPFF_LS_MPLS_REMOTE_ADDR],
1047                                           tvb, stlv_offset+4+i, 4, FALSE);
1048                     break;
1049
1050                 case MPLS_LINK_TE_METRIC:
1051                 case MPLS_LINK_COLOR:
1052                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1053                                              "%s: %u", stlv_name,
1054                                              tvb_get_ntohl(tvb, stlv_offset + 4));
1055                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1056                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1057                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1058                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1059                                         stlv_len);
1060                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %u", stlv_name,
1061                                         tvb_get_ntohl(tvb, stlv_offset + 4));
1062                     break;
1063
1064                 case MPLS_LINK_MAX_BW:
1065                 case MPLS_LINK_MAX_RES_BW:
1066                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1067                                              "%s: %.10g", stlv_name,
1068                                              tvb_get_ntohieee_float(tvb, stlv_offset + 4));
1069                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1070                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1071                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1072                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1073                                         stlv_len);
1074                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %.10g", stlv_name,
1075                                         tvb_get_ntohieee_float(tvb, stlv_offset + 4));
1076                     break;
1077
1078                 case MPLS_LINK_UNRES_BW:
1079                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1080                                              "%s", stlv_name);
1081                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1082                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1083                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1084                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1085                                         stlv_len);
1086                     for (i = 0; i < 8; i++) {
1087                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+(i*4), 4,
1088                                             "Pri %d: %.10g bytes/s (%.0f bits/s)", i,
1089                                             tvb_get_ntohieee_float(tvb, stlv_offset + 4 + i*4),
1090                                             tvb_get_ntohieee_float(tvb, stlv_offset + 4 + i*4) * 8.0);
1091                     }
1092                     break;
1093
1094                 case MPLS_LINK_LOCAL_ID:
1095                 case MPLS_LINK_REMOTE_ID:
1096                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1097                                              "%s: %d (0x%x)", stlv_name,
1098                                              tvb_get_ntohl(tvb, stlv_offset + 4),
1099                                              tvb_get_ntohl(tvb, stlv_offset + 4));
1100                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1101                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1102                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1103                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1104                                         stlv_len);
1105                     proto_tree_add_item(stlv_tree, 
1106                                         stlv_type==MPLS_LINK_LOCAL_ID ? 
1107                                         ospf_filter[OSPFF_LS_MPLS_LOCAL_IFID] : 
1108                                         ospf_filter[OSPFF_LS_MPLS_REMOTE_IFID],
1109                                         tvb, stlv_offset+4, 4, FALSE);
1110                     break;
1111
1112                 case MPLS_LINK_IF_SWITCHING_DESC:
1113                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1114                                              "%s", stlv_name);
1115                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1116                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1117                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1118                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1119                                         stlv_len);
1120                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Switching Type: %s", 
1121                                         val_to_str(tvb_get_guint8(tvb,stlv_offset+4), 
1122                                                    gmpls_switching_type_str, "Unknown (%d)"));
1123                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+5, 1, "Encoding: %s", 
1124                                         val_to_str(tvb_get_guint8(tvb,stlv_offset+5), 
1125                                                    gmpls_lsp_enc_str, "Unknown (%d)"));
1126                     for (i = 0; i < 8; i++) {
1127                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+8+(i*4), 4,
1128                                             "Pri %d: %.10g bytes/s (%.0f bits/s)", i,
1129                                             tvb_get_ntohieee_float(tvb, stlv_offset + 8 + i*4),
1130                                             tvb_get_ntohieee_float(tvb, stlv_offset + 8 + i*4) * 8.0);
1131                     }
1132                     break;
1133
1134                 default:
1135                     proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1136                                         "Unknown Link sub-TLV: %u", stlv_type);
1137                     break;
1138                 }
1139                 stlv_offset += ((stlv_len+4+3)/4)*4;
1140             }
1141             break;
1142
1143         default:
1144             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4, 
1145                                      "Unknown LSA: %u", tlv_type);
1146             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
1147             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: %u - Unknown",
1148                                 tlv_type);
1149             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
1150                                 tlv_length);
1151             proto_tree_add_text(tlv_tree, tvb, offset+4, tlv_length, "TLV Data");
1152             break;
1153         }
1154
1155         offset += tlv_length + 4;
1156         length -= tlv_length + 4;
1157     }
1158 }
1159
1160 /*
1161  * Dissect opaque LSAs
1162  */
1163 static void
1164 dissect_ospf_lsa_opaque(tvbuff_t *tvb, int offset, proto_tree *tree,
1165                         guint8 ls_id_type, guint32 length)
1166 {
1167     switch (ls_id_type) {
1168
1169     case OSPF_LSA_MPLS_TE:
1170         dissect_ospf_lsa_mpls(tvb, offset, tree, length);
1171         break;
1172
1173     default:
1174         proto_tree_add_text(tree, tvb, offset, length,
1175                             "Unknown LSA Type %u", ls_id_type);
1176         break;
1177     } /* switch on opaque LSA id */
1178 }
1179
1180 static int
1181 dissect_ospf_v2_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
1182                  gboolean disassemble_body)
1183 {
1184     proto_tree *ospf_lsa_tree;
1185     proto_item *ti; 
1186
1187     guint8               ls_type;
1188     guint16              ls_length;
1189     int                  end_offset;
1190     guint8               nr_links;
1191     guint16              nr_tos;
1192
1193     /* router LSA */
1194     guint8               link_type;
1195     guint16              link_counter;
1196     guint8               tos_counter;
1197     char                *link_type_str;
1198     char                *link_id;
1199
1200     /* AS-external LSA */
1201     guint8               options;
1202
1203     /* opaque LSA */
1204     guint8               ls_id_type;
1205
1206     ls_type = tvb_get_guint8(tvb, offset + 3);
1207     ls_length = tvb_get_ntohs(tvb, offset + 18);
1208     end_offset = offset + ls_length;
1209
1210     if (disassemble_body) {
1211         ti = proto_tree_add_text(tree, tvb, offset, ls_length, 
1212                                  "LS Type: %s", 
1213                                  val_to_str(ls_type, ls_type_vals, "Unknown (%d)")); 
1214     } else {
1215         ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
1216                                  "LSA Header"); 
1217     }
1218     ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
1219
1220     proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
1221                         tvb_get_ntohs(tvb, offset));
1222     dissect_ospf_options(tvb, offset + 2, ospf_lsa_tree, OSPF_VERSION_2);
1223     proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_LS_TYPE], tvb, 
1224                         offset + 3, 1, FALSE); 
1225     proto_tree_add_item_hidden(ospf_lsa_tree, 
1226                                ospf_filter[ospf_ls_type_to_filter(ls_type)], tvb, 
1227                                offset + 3, 1, FALSE); 
1228
1229     if (is_opaque(ls_type)) {
1230         ls_id_type = tvb_get_guint8(tvb, offset + 4);
1231         proto_tree_add_uint(ospf_lsa_tree, ospf_filter[OSPFF_LS_OPAQUE_TYPE],
1232                             tvb, offset + 4, 1, ls_id_type);
1233
1234         switch (ls_id_type) {
1235
1236         case OSPF_LSA_MPLS_TE:
1237             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 1, "Link State ID TE-LSA Reserved: %u",
1238                                 tvb_get_guint8(tvb, offset + 5));
1239             proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_LS_MPLS_TE_INSTANCE],
1240                                 tvb, offset + 6, 2, FALSE);
1241             break;
1242
1243         default:
1244             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3, "Link State ID Opaque ID: %u",
1245                                 tvb_get_ntoh24(tvb, offset + 5));
1246             break;
1247         }
1248     } else {
1249         ls_id_type = 0;
1250         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
1251                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
1252     }
1253
1254     proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_ADV_ROUTER],
1255                         tvb, offset + 8, 4, FALSE);
1256     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%04x",
1257                         tvb_get_ntohl(tvb, offset + 12));
1258     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
1259                         tvb_get_ntohs(tvb, offset + 16));
1260
1261     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
1262                         ls_length);
1263
1264     /* skip past the LSA header to the body */
1265     offset += OSPF_LSA_HEADER_LENGTH;
1266     if (ls_length <= OSPF_LSA_HEADER_LENGTH)
1267         return offset;  /* no data, or bogus length */
1268     ls_length -= OSPF_LSA_HEADER_LENGTH;
1269
1270     if (!disassemble_body)
1271         return offset;
1272
1273     switch (ls_type){
1274
1275     case OSPF_LSTYPE_ROUTER:
1276         /* again: flags should be secified in detail */
1277         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x",
1278                             tvb_get_guint8(tvb, offset));
1279         nr_links = tvb_get_ntohs(tvb, offset + 2);
1280         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "Number of Links: %u",
1281                             nr_links);
1282         offset += 4;
1283         /* nr_links links follow 
1284          * maybe we should put each of the links into its own subtree ???
1285          */
1286         for (link_counter = 1; link_counter <= nr_links; link_counter++) {
1287             /* check the Link Type and ID */
1288             link_type = tvb_get_guint8(tvb, offset + 8);
1289             switch (link_type) {
1290
1291             case OSPF_LINK_PTP:
1292                 link_type_str="Point-to-point connection to another router";
1293                 link_id="Neighboring router's Router ID";
1294                 break;
1295
1296             case OSPF_LINK_TRANSIT:
1297                 link_type_str="Connection to a transit network";
1298                 link_id="IP address of Designated Router";
1299                 break;
1300
1301             case OSPF_LINK_STUB:
1302                 link_type_str="Connection to a stub network";
1303                 link_id="IP network/subnet number";
1304                 break;
1305
1306             case OSPF_LINK_VIRTUAL:
1307                 link_type_str="Virtual link";
1308                 link_id="Neighboring router's Router ID";
1309                 break;
1310
1311             default:
1312                 link_type_str="Unknown link type";
1313                 link_id="Unknown link ID";
1314                 break;
1315             }
1316
1317             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "%s: %s", link_id,
1318                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1319
1320             /* link_data should be specified in detail (e.g. network mask) (depends on link type)*/
1321             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link Data: %s",
1322                                 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
1323
1324             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 1, "Link Type: %u - %s",
1325                                 link_type, link_type_str);
1326             nr_tos = tvb_get_guint8(tvb, offset + 9);
1327             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 9, 1, "Number of TOS metrics: %u",
1328                                 nr_tos);
1329             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 10, 2, "TOS 0 metric: %u",
1330                                 tvb_get_ntohs(tvb, offset + 10));
1331
1332             offset += 12;
1333
1334             /* nr_tos metrics may follow each link 
1335              * ATTENTION: TOS metrics are not tested (I don't have TOS
1336              * based routing)
1337              * please send me a mail if it is/isn't working
1338              */
1339             for (tos_counter = 1; tos_counter <= nr_tos; tos_counter++) {
1340                 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
1341                                     tvb_get_guint8(tvb, offset),
1342                                     tvb_get_ntohs(tvb, offset + 2));
1343                 offset += 4;
1344             }
1345         }
1346         break;
1347
1348     case OSPF_LSTYPE_NETWORK:
1349         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
1350                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1351         offset += 4;
1352
1353         while (offset < end_offset) {
1354             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
1355                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1356             offset += 4;
1357         }
1358         break;
1359
1360     case OSPF_LSTYPE_SUMMERY:
1361     /* Type 3 and 4 LSAs have the same format */
1362     case OSPF_LSTYPE_ASBR:
1363         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
1364                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1365         offset += 4;
1366
1367         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Metric: %u",
1368                             tvb_get_ntoh24(tvb, offset + 1));
1369         offset += 4;
1370
1371         /* TOS-specific information, if any */
1372         while (offset < end_offset) {
1373             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
1374                                 tvb_get_guint8(tvb, offset),
1375                                 tvb_get_ntoh24(tvb, offset + 1));
1376             offset += 4;
1377         }
1378         break;
1379
1380     case OSPF_LSTYPE_ASEXT:
1381     case OSPF_LSTYPE_ASEXT7:
1382         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s", 
1383                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1384         offset += 4;
1385
1386         options = tvb_get_guint8(tvb, offset);
1387         if (options & 0x80) { /* check wether or not E bit is set */
1388             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1389                     "External Type: Type 2 (metric is larger than any other link state path)");
1390         } else {
1391             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1392                     "External Type: Type 1 (metric is specified in the same units as interface cost)");
1393         }
1394         /* the metric field of a AS-external LAS is specified in 3 bytes */
1395         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3, "Metric: %u",
1396                             tvb_get_ntoh24(tvb, offset + 1));
1397         offset += 4;
1398
1399         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s", 
1400                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1401         offset += 4;
1402
1403         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
1404                             tvb_get_ntohl(tvb, offset));
1405         offset += 4;
1406
1407         /* TOS-specific information, if any */
1408         while (offset < end_offset) {
1409             options = tvb_get_guint8(tvb, offset);
1410             if (options & 0x80) { /* check wether or not E bit is set */
1411                 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1412                         "External Type: Type 2 (metric is larger than any other link state path)");
1413             } else {
1414                 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1415                         "External Type: Type 1 (metric is specified in the same units as interface cost)");
1416             }
1417             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
1418                                 options & 0x7F,
1419                                 tvb_get_ntoh24(tvb, offset + 1));
1420             offset += 4;
1421
1422             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s", 
1423                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1424             offset += 4;
1425
1426             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
1427                                 tvb_get_ntohl(tvb, offset));
1428             offset += 4;
1429         }
1430         break;
1431
1432     case OSPF_LSTYPE_OP_LINKLOCAL:
1433     case OSPF_LSTYPE_OP_AREALOCAL:
1434     case OSPF_LSTYPE_OP_ASWIDE:
1435         /*
1436          * RFC 2370 opaque LSAs.
1437          */
1438         dissect_ospf_lsa_opaque(tvb, offset, ospf_lsa_tree, ls_id_type,
1439                                 ls_length);
1440         offset += ls_length;
1441         break;
1442
1443     default:
1444         /* unknown LSA type */
1445         proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
1446                             "Unknown LSA Type");
1447         offset += ls_length;
1448         break;
1449     }
1450     /* return the offset of the next LSA */
1451     return offset;
1452 }
1453
1454 static int
1455 dissect_ospf_v3_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
1456                  gboolean disassemble_body)
1457 {
1458     proto_tree *ospf_lsa_tree;
1459     proto_item *ti; 
1460
1461     guint16              ls_type;
1462     guint16              ls_length;
1463     int                  end_offset;
1464     guint8               reserved;
1465
1466     /* router LSA */
1467     guint8               link_type;
1468     char                *link_type_str;
1469     guint32              metric;
1470
1471     guint8               router_lsa_flags;
1472     char                 router_lsa_flags_string[5];
1473
1474     guint8               router_priority;
1475     guint32              number_prefixes;
1476     guint8               prefix_length;
1477     guint16              reserved16;
1478
1479     guint16              referenced_ls_type;
1480
1481     guint8               flags;
1482     guint8               flags_string[4];
1483     guint32              external_route_tag;
1484
1485
1486     ls_type = tvb_get_ntohs(tvb, offset + 2);
1487     ls_length = tvb_get_ntohs(tvb, offset + 18);
1488     end_offset = offset + ls_length;
1489
1490     if (disassemble_body) {
1491         ti = proto_tree_add_text(tree, tvb, offset, ls_length,
1492                                  "%s (Type: 0x%04x)", val_to_str(ls_type, v3_ls_type_vals,"Unknown"), ls_type); 
1493     } else {
1494         ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
1495                                  "LSA Header"); 
1496     }
1497     ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
1498
1499     proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
1500                         tvb_get_ntohs(tvb, offset));
1501
1502     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "LSA Type: 0x%04x (%s)",
1503                         ls_type, val_to_str(ls_type, v3_ls_type_vals,"Unkown"));
1504
1505     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
1506                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
1507
1508     proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_ADV_ROUTER],
1509                         tvb, offset + 8, 4, FALSE);
1510     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: %d",
1511                         tvb_get_ntohl(tvb, offset + 12));
1512     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
1513                         tvb_get_ntohs(tvb, offset + 16));
1514
1515     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
1516                         ls_length);
1517
1518     /* skip past the LSA header to the body */
1519     offset += OSPF_LSA_HEADER_LENGTH;
1520     ls_length -= OSPF_LSA_HEADER_LENGTH;
1521
1522     if (!disassemble_body)
1523         return offset;
1524
1525     switch (ls_type){
1526
1527
1528     case OSPF_V3_LSTYPE_ROUTER:
1529
1530       /* flags field in an router-lsa */
1531         router_lsa_flags=tvb_get_guint8(tvb,offset);
1532         if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_B)
1533             router_lsa_flags_string[3] = 'B';
1534         else
1535             router_lsa_flags_string[3] = '.';
1536         if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_E)
1537             router_lsa_flags_string[2] = 'E';
1538         else
1539             router_lsa_flags_string[2] = '.';
1540         if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_V)
1541             router_lsa_flags_string[1] = 'V';
1542         else
1543             router_lsa_flags_string[1] = '.';
1544         if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_W)
1545             router_lsa_flags_string[0] = 'W';
1546         else
1547             router_lsa_flags_string[0] = '.';
1548
1549         router_lsa_flags_string[4]=0;
1550
1551         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x (%s)",
1552                             router_lsa_flags, router_lsa_flags_string);
1553
1554         /* options field in an router-lsa */
1555         dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
1556
1557         /* skip the router-lsa flags and options */
1558         offset+=4;
1559         ls_length-=4;
1560
1561         if (ls_length > 0)
1562              proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
1563                    "Router Interfaces:"); 
1564
1565         /* scan all router-lsa router interfaces */
1566         /* maybe we should put each of the links into its own subtree ??? */
1567         while (ls_length > 0 ) {
1568
1569             /* check the type */
1570             link_type = tvb_get_guint8(tvb, offset);
1571             switch (link_type) {
1572
1573                 case OSPF_V3_LINK_PTP:
1574                     link_type_str="Point-to-point connection to another router";
1575                     break;
1576
1577                 case OSPF_V3_LINK_TRANSIT:
1578                     link_type_str="Connection to a transit network";
1579                     break;
1580
1581                 case OSPF_V3_LINK_RESERVED:
1582                     link_type_str="Connection to a stub network";
1583                     break;
1584
1585                 case OSPF_V3_LINK_VIRTUAL:
1586                     link_type_str="Virtual link";
1587                     break;
1588
1589                 default:
1590                     link_type_str="Unknown link type";
1591                     break;
1592             }
1593
1594             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Type: %u (%s)", link_type,link_type_str);
1595
1596             /* reserved field */
1597             reserved = tvb_get_guint8(tvb, offset+1);
1598             proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 1,
1599                (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
1600
1601             /* metric */
1602             metric=tvb_get_ntohs(tvb, offset+2);
1603             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2,"Metric: %u",metric);
1604
1605             /* Interface ID */
1606             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Interface ID: %u",
1607                         tvb_get_ntohl(tvb, offset + 4));
1608
1609             /* Neighbor Interface ID */
1610             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Neighbor Interface ID: %u",
1611                         tvb_get_ntohl(tvb, offset + 8));
1612
1613             /* Neighbor Router ID */
1614             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "Neighbor Router ID: %s",
1615                 ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
1616
1617             /* skip to the (possible) next entry */
1618             offset+=16;
1619             ls_length-=16;
1620
1621         }
1622         break;
1623
1624     case OSPF_V3_LSTYPE_NETWORK:
1625
1626         /* reserved field */
1627         reserved = tvb_get_guint8(tvb, offset);
1628         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1629                (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
1630
1631         /* options field in an network-lsa */
1632         dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
1633
1634         offset += 4;
1635         ls_length-=4;
1636
1637         while (ls_length > 0 ) {
1638             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
1639                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1640             ls_length-=4;
1641             offset += 4;
1642         }
1643         break;
1644
1645
1646     case OSPF_V3_LSTYPE_INTER_AREA_PREFIX:
1647
1648         /* reserved field */
1649         reserved = tvb_get_guint8(tvb, offset);
1650         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1651                (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
1652
1653         /* metric */
1654         metric=tvb_get_ntoh24(tvb, offset+11);
1655         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3,"Metric: %u",metric);
1656
1657         /* prefix length */
1658         prefix_length=tvb_get_guint8(tvb, offset+4);
1659         proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length);
1660
1661         /* prefix options */
1662         dissect_ospf_v3_prefix_options(tvb, offset+5, ospf_lsa_tree);
1663
1664         /* 16 bits reserved */
1665         reserved16=tvb_get_ntohs(tvb, offset+6);
1666         proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,
1667                (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved16);
1668
1669         offset+=8;
1670
1671         /* address_prefix */
1672         dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
1673
1674         offset+=(prefix_length+31)/32*4;
1675
1676         break;
1677
1678
1679     case OSPF_V3_LSTYPE_INTER_AREA_ROUTER:
1680
1681         /* reserved field */
1682         reserved = tvb_get_guint8(tvb, offset);
1683         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1684                (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
1685
1686         /* options field in an inter-area-router-lsa */
1687         dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
1688
1689         /* reserved field */
1690         reserved = tvb_get_guint8(tvb, offset+4);
1691         proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1,
1692                (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
1693
1694         /* metric */
1695         metric=tvb_get_ntoh24(tvb, offset+6);
1696         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 6, 3,"Metric: %u",metric);
1697
1698         /* Destination Router ID */
1699         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Destination Router ID: %s",
1700                 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
1701
1702         offset+=12;
1703         break;
1704
1705
1706     case OSPF_V3_LSTYPE_AS_EXTERNAL:
1707
1708         /* flags */
1709         flags=tvb_get_guint8(tvb, offset);
1710         if (flags & OSPF_V3_AS_EXTERNAL_FLAG_E)
1711             flags_string[0] = 'E';
1712         else
1713             flags_string[0] = '.';
1714         if (flags & OSPF_V3_AS_EXTERNAL_FLAG_F)
1715             flags_string[1] = 'F';
1716         else
1717             flags_string[1] = '.';
1718         if (flags & OSPF_V3_AS_EXTERNAL_FLAG_T)
1719             flags_string[2] = 'T';
1720         else
1721             flags_string[2] = '.';
1722
1723         flags_string[3]=0;
1724
1725         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x (%s)",
1726                             flags, flags_string);
1727         
1728         /* 24 bits metric */
1729         metric=tvb_get_ntoh24(tvb, offset+1);
1730         proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 3,
1731                                 "Metric: %u", metric);
1732
1733         /* prefix length */
1734         prefix_length=tvb_get_guint8(tvb, offset+4);
1735         proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length);
1736
1737         /* prefix options */
1738         dissect_ospf_v3_prefix_options(tvb, offset+5, ospf_lsa_tree);
1739
1740         /* referenced LS type */
1741         referenced_ls_type=tvb_get_ntohs(tvb, offset+6);
1742         proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,"Referenced LS type 0x%04x (%s)",
1743                             referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
1744
1745         offset+=8;
1746
1747         /* address_prefix */
1748         dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
1749        
1750         offset+=(prefix_length+31)/32*4;
1751
1752         /* Forwarding Address (optional - only if F-flag is on) */
1753         if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_F) ) {
1754             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 16,"Forwarding Address: %s",
1755               ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16)));
1756
1757             offset+=16;
1758         }
1759
1760         /* External Route Tag (optional - only if T-flag is on) */
1761         if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_T) ) {
1762             external_route_tag=tvb_get_ntohl(tvb, offset);
1763             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4,"External Route Tag: 0x%04x",
1764                                 external_route_tag);
1765
1766             offset+=4;
1767         }
1768
1769         /* Referenced Link State ID (optional - only if Referenced LS type is non-zero */
1770         if ( (offset < end_offset) && (referenced_ls_type != 0) ) {
1771             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Referenced Link State ID: %s", 
1772                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1773             offset+=4;
1774         }
1775
1776         break;
1777
1778     case OSPF_V3_LSTYPE_LINK:
1779
1780         /* router priority */
1781         router_priority=tvb_get_guint8(tvb, offset);
1782         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Router Priority: %u", router_priority);
1783
1784         /* options field in an link-lsa */
1785         dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
1786
1787         /* Link-local Interface Address */
1788         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 16, "Link-local Interface Address: %s",
1789            ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset + 4, 16)));
1790
1791         /* Number prefixes */
1792         number_prefixes=tvb_get_ntohl(tvb, offset + 20);
1793         proto_tree_add_text(ospf_lsa_tree, tvb, offset+20, 4, "# prefixes: %d",number_prefixes);
1794
1795         offset+=24;
1796
1797         while (number_prefixes > 0) {
1798
1799             /* prefix length */
1800             prefix_length=tvb_get_guint8(tvb, offset);
1801             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length);
1802
1803             /* prefix options */
1804             dissect_ospf_v3_prefix_options(tvb, offset+1, ospf_lsa_tree);
1805
1806             /* 16 bits reserved */
1807             reserved16=tvb_get_ntohs(tvb, offset+2);
1808             proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,
1809                (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved16);
1810
1811             offset+=4;
1812
1813             /* address_prefix */
1814             dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
1815        
1816             offset+=(prefix_length+31)/32*4;
1817
1818             number_prefixes--;
1819
1820         }             
1821         break;
1822
1823     case OSPF_V3_LSTYPE_INTRA_AREA_PREFIX:
1824
1825         /* # prefixes */
1826         number_prefixes=tvb_get_ntohs(tvb, offset);
1827         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2,"# prefixes: %u",number_prefixes);
1828
1829         /* referenced LS type */
1830         referenced_ls_type=tvb_get_ntohs(tvb, offset+2);
1831         proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,"Referenced LS type 0x%04x (%s)",
1832                             referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
1833
1834         /* Referenced Link State ID */
1835         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Referenced Link State ID: %s", 
1836                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
1837
1838         /* Referenced Advertising Router */
1839         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Referenced Advertising Router: %s", 
1840                             ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
1841
1842         offset+=12;
1843
1844         while (number_prefixes > 0) {
1845
1846             /* prefix length */
1847             prefix_length=tvb_get_guint8(tvb, offset);
1848             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length);
1849
1850             /* prefix options */
1851             dissect_ospf_v3_prefix_options(tvb, offset+1, ospf_lsa_tree);
1852
1853             /* 16 bits metric */
1854             metric=tvb_get_ntohs(tvb, offset+2);
1855             proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,
1856                                 "Metric: %u", metric);
1857
1858             offset+=4;
1859
1860             /* address_prefix */
1861             dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
1862        
1863             offset+=(prefix_length+31)/32*4;
1864
1865             number_prefixes--;
1866         }
1867         break;
1868
1869     default:
1870         /* unknown LSA type */
1871         proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
1872                             "Unknown LSA Type 0x%04x",ls_type);
1873         offset += ls_length;
1874         break;
1875     }
1876     /* return the offset of the next LSA */
1877     return offset;
1878 }
1879
1880
1881 static void
1882 dissect_ospf_options(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
1883 {
1884     guint8 options_ospfv2;
1885     guint32 options_ospfv3;
1886     char options_string[20] = "";
1887
1888     /* ATTENTION !!! no check for length of options string  - with OSPFv3 maximum length is 14 characters */
1889
1890     switch ( version ) {
1891
1892         case OSPF_VERSION_2:
1893
1894             options_ospfv2 = tvb_get_guint8(tvb, offset);
1895
1896             if (options_ospfv2 & OSPF_V2_OPTIONS_E)
1897                 strcat(options_string, "E");
1898
1899             if (options_ospfv2 & OSPF_V2_OPTIONS_MC) {
1900                 if (options_string[0] != '\0')
1901                     strcat(options_string, "/");
1902                 strcat(options_string, "MC");
1903             }
1904
1905             if (options_ospfv2 & OSPF_V2_OPTIONS_NP) {
1906                 if (options_string[0] != '\0')
1907                     strcat(options_string, "/");
1908                 strcat(options_string, "NP");
1909             }
1910
1911             if (options_ospfv2 & OSPF_V2_OPTIONS_EA) {
1912                 if (options_string[0] != '\0')
1913                     strcat(options_string, "/");
1914                 strcat(options_string, "EA");
1915             }
1916
1917             if (options_ospfv2 & OSPF_V2_OPTIONS_DC) {
1918                 if (options_string[0] != '\0')
1919                     strcat(options_string, "/");
1920                 strcat(options_string, "DC");
1921             }
1922
1923             if (options_ospfv2 & OSPF_V2_OPTIONS_O) {
1924                 if (options_string[0] != '\0')
1925                     strcat(options_string, "/");
1926                 strcat(options_string, "O");
1927             }
1928
1929             if (options_ospfv2 & OSPF_V2_OPTIONS_DN) {
1930                 if (options_string[0] != '\0')
1931                     strcat(options_string, "/");
1932                 strcat(options_string, "DN");  
1933             }
1934
1935             proto_tree_add_text(tree, tvb, offset, 1, "Options: 0x%x (%s)",
1936                         options_ospfv2, options_string);
1937             break;
1938
1939
1940         case OSPF_VERSION_3:
1941
1942             options_ospfv3 = tvb_get_ntoh24(tvb, offset);
1943
1944             if (options_ospfv3 & OSPF_V3_OPTIONS_V6)
1945                 strcat(options_string, "V6");
1946
1947             if (options_ospfv3 & OSPF_V3_OPTIONS_E)
1948                 if (options_string[0] != '\0')
1949                     strcat(options_string, "/");
1950                 strcat(options_string, "E");
1951
1952             if (options_ospfv3 & OSPF_V3_OPTIONS_MC) {
1953                 if (options_string[0] != '\0')
1954                     strcat(options_string, "/");
1955                 strcat(options_string, "MC");
1956             }
1957
1958             if (options_ospfv3 & OSPF_V3_OPTIONS_N) {
1959                 if (options_string[0] != '\0')
1960                     strcat(options_string, "/");
1961                 strcat(options_string, "N");
1962             }
1963
1964             if (options_ospfv3 & OSPF_V3_OPTIONS_R) {
1965                 if (options_string[0] != '\0')
1966                     strcat(options_string, "/");
1967                 strcat(options_string, "R");
1968             }
1969
1970             if (options_ospfv3 & OSPF_V3_OPTIONS_DC) {
1971                 if (options_string[0] != '\0')
1972                     strcat(options_string, "/");
1973                 strcat(options_string, "DC");
1974             }
1975
1976             proto_tree_add_text(tree, tvb, offset, 3, "Options: 0x%x (%s)",
1977                         options_ospfv3, options_string);
1978             break;
1979
1980         default:
1981             break;
1982     }
1983
1984 }
1985
1986
1987 static void dissect_ospf_v3_prefix_options(tvbuff_t *tvb, int offset, proto_tree *tree)
1988 {
1989
1990     guint8 prefix_options;
1991     char prefix_options_string[11];
1992     guint8 position;
1993
1994     position=0;
1995     
1996     prefix_options=tvb_get_guint8(tvb, offset);
1997
1998     strcpy(prefix_options_string,"");
1999
2000     if (prefix_options & OSPF_V3_PREFIX_OPTION_P) {
2001         strcat(prefix_options_string, "P");
2002         position++;
2003     }
2004
2005     if (prefix_options & OSPF_V3_PREFIX_OPTION_MC) {
2006         if ( (position > 0) && (prefix_options_string[position-1] != '/') ) {
2007             strcat(prefix_options_string, "/");
2008             position++;
2009         }
2010         strcat(prefix_options_string, "MC");
2011         position+=2;
2012     }
2013
2014     if (prefix_options & OSPF_V3_PREFIX_OPTION_LA) {
2015         if ( (position > 0) && (prefix_options_string[position-1] != '/') ) {
2016             strcat(prefix_options_string, "/");
2017             position++;
2018         }
2019         strcat(prefix_options_string, "LA");
2020         position+=2;
2021     }
2022
2023     if (prefix_options & OSPF_V3_PREFIX_OPTION_NU) {
2024         if ( (position > 0) && (prefix_options_string[position-1] != '/') ) {
2025             strcat(prefix_options_string, "/");
2026             position++;
2027         }
2028         strcat(prefix_options_string, "NU");
2029     }
2030
2031     prefix_options_string[10]=0;
2032
2033     proto_tree_add_text(tree, tvb, offset, 1, "PrefixOptions: 0x%02x (%s)",prefix_options, prefix_options_string);
2034
2035 }
2036
2037
2038 static void dissect_ospf_v3_address_prefix(tvbuff_t *tvb, int offset, int prefix_length, proto_tree *tree)
2039 {
2040
2041     guint8 value;
2042     guint8 position;
2043     guint8 bufpos;
2044     gchar  buffer[32+7];
2045     gchar  bytebuf[3];
2046     guint8 bytes_to_process;
2047     int start_offset;
2048
2049     start_offset=offset;
2050     position=0;
2051     bufpos=0;
2052     bytes_to_process=((prefix_length+31)/32)*4;
2053
2054     while (bytes_to_process > 0 ) {
2055
2056         value=tvb_get_guint8(tvb, offset);
2057
2058         if ( (position > 0) && ( (position%2) == 0 ) )
2059             buffer[bufpos++]=':';
2060
2061         sprintf(bytebuf,"%02x",value);
2062         buffer[bufpos++]=bytebuf[0];        
2063         buffer[bufpos++]=bytebuf[1];        
2064         
2065         position++;
2066         offset++;
2067         bytes_to_process--;
2068     }
2069
2070     buffer[bufpos]=0;  
2071     proto_tree_add_text(tree, tvb, start_offset, ((prefix_length+31)/32)*4, "Address Prefix: %s",buffer);
2072
2073 }
2074
2075
2076 void
2077 proto_register_ospf(void)
2078 {
2079     static gint *ett[] = {
2080         &ett_ospf,
2081         &ett_ospf_hdr,
2082         &ett_ospf_hello,
2083         &ett_ospf_desc,
2084         &ett_ospf_lsr,
2085         &ett_ospf_lsa,
2086         &ett_ospf_lsa_upd,
2087         &ett_ospf_lsa_mpls,
2088         &ett_ospf_lsa_mpls_router,
2089         &ett_ospf_lsa_mpls_link,
2090         &ett_ospf_lsa_mpls_link_stlv
2091     };
2092
2093     proto_ospf = proto_register_protocol("Open Shortest Path First",
2094                                          "OSPF", "ospf");
2095     proto_register_field_array(proto_ospf, ospff_info, array_length(ospff_info));
2096     proto_register_subtree_array(ett, array_length(ett));
2097 }
2098
2099 void
2100 proto_reg_handoff_ospf(void)
2101 {
2102     dissector_handle_t ospf_handle;
2103
2104     ospf_handle = create_dissector_handle(dissect_ospf, proto_ospf);
2105     dissector_add("ip.proto", IP_PROTO_OSPF, ospf_handle);
2106     data_handle = find_dissector("data");
2107 }