From Michael Rozhavsky:
[metze/wireshark/wip.git] / epan / dissectors / 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$
6  *
7  * Added support for OSPF restart signaling:
8  *       draft-nguyen-ospf-lls-05.txt
9  *       draft-nguyen-ospf-oob-resync-05.txt
10  *       draft-nguyen-ospf-restart-05.txt
11  *   - (c) 2005 Michael Rozhavsky <mrozhavsky@fortinet.com>
12  * 
13  * At this time, this module is able to analyze OSPF
14  * packets as specified in RFC2328. MOSPF (RFC1584) and other
15  * OSPF Extensions which introduce new Packet types
16  * (e.g the External Atributes LSA) are not supported.
17  * Furthermore RFC2740 (OSPFv3 - OSPF for IPv6) is now supported
18  *   - (c) 2001 Palle Lyckegaard <palle[AT]lyckegaard.dk>
19  *
20  * Added support to E-NNI routing (OIF2003.259.02)
21  *   - (c) 2004 Roberto Morro <roberto.morro[AT]tilab.com>
22
23  * TOS - support is not fully implemented
24  *
25  * Ethereal - Network traffic analyzer
26  * By Gerald Combs <gerald@ethereal.com>
27  * Copyright 1998 Gerald Combs
28  *
29  * This program is free software; you can redistribute it and/or
30  * modify it under the terms of the GNU General Public License
31  * as published by the Free Software Foundation; either version 2
32  * of the License, or (at your option) any later version.
33  *
34  * This program is distributed in the hope that it will be useful,
35  * but WITHOUT ANY WARRANTY; without even the implied warranty of
36  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37  * GNU General Public License for more details.
38  *
39  * You should have received a copy of the GNU General Public License
40  * along with this program; if not, write to the Free Software
41  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
42  */
43
44 #ifdef HAVE_CONFIG_H
45 # include "config.h"
46 #endif
47
48 #include <stdio.h>
49 #include <string.h>
50
51 #include <glib.h>
52 #include <epan/packet.h>
53 #include <epan/ipproto.h>
54 #include <epan/in_cksum.h>
55 #include <epan/emem.h>
56 #include "packet-rsvp.h"
57
58 #define OSPF_VERSION_2 2
59 #define OSPF_VERSION_3 3
60 #define OSPF_VERSION_2_HEADER_LENGTH    24
61 #define OSPF_VERSION_3_HEADER_LENGTH    16
62
63
64 #define OSPF_HELLO      1
65 #define OSPF_DB_DESC    2
66 #define OSPF_LS_REQ     3
67 #define OSPF_LS_UPD     4
68 #define OSPF_LS_ACK     5
69
70 static const value_string pt_vals[] = {
71         {OSPF_HELLO,   "Hello Packet"   },
72         {OSPF_DB_DESC, "DB Descr."      },
73         {OSPF_LS_REQ,  "LS Request"     },
74         {OSPF_LS_UPD,  "LS Update"      },
75         {OSPF_LS_ACK,  "LS Acknowledge" },
76         {0,             NULL            }
77 };
78
79 #define OSPF_AUTH_NONE          0
80 #define OSPF_AUTH_SIMPLE        1
81 #define OSPF_AUTH_CRYPT         2
82
83 static const value_string auth_vals[] = {
84         {OSPF_AUTH_NONE,   "Null"            },
85         {OSPF_AUTH_SIMPLE, "Simple password" },
86         {OSPF_AUTH_CRYPT,  "Cryptographic"   },
87         {0,                NULL              }
88 };
89
90 #define OSPF_V2_OPTIONS_E               0x02
91 #define OSPF_V2_OPTIONS_MC              0x04
92 #define OSPF_V2_OPTIONS_NP              0x08
93 #define OSPF_V2_OPTIONS_L               0x10
94 #define OSPF_V2_OPTIONS_DC              0x20
95 #define OSPF_V2_OPTIONS_O               0x40
96 #define OSPF_V2_OPTIONS_DN              0x80
97 #define OSPF_V3_OPTIONS_V6              0x01
98 #define OSPF_V3_OPTIONS_E               0x02
99 #define OSPF_V3_OPTIONS_MC              0x04
100 #define OSPF_V3_OPTIONS_N               0x08
101 #define OSPF_V3_OPTIONS_R               0x10
102 #define OSPF_V3_OPTIONS_DC              0x20
103
104 #define OSPF_LLS_EXT_OPTIONS_LR         0x00000001
105 #define OSPF_LLS_EXT_OPTIONS_RS         0x00000002
106
107 #define OSPF_DBD_FLAG_MS        1
108 #define OSPF_DBD_FLAG_M         2
109 #define OSPF_DBD_FLAG_I         4
110 #define OSPF_DBD_FLAG_R         8
111
112 #define OSPF_LS_REQ_LENGTH      12
113
114 #define OSPF_LSTYPE_ROUTER      1
115 #define OSPF_LSTYPE_NETWORK     2
116 #define OSPF_LSTYPE_SUMMERY     3
117 #define OSPF_LSTYPE_ASBR        4
118 #define OSPF_LSTYPE_ASEXT       5
119 #define OSPF_LSTYPE_GRPMEMBER   6
120 #define OSPF_LSTYPE_ASEXT7      7
121 #define OSPF_LSTYPE_EXTATTR     8
122 #define OSPF_V3_LSTYPE_ROUTER                0x2001
123 #define OSPF_V3_LSTYPE_NETWORK               0x2002
124 #define OSPF_V3_LSTYPE_INTER_AREA_PREFIX     0x2003
125 #define OSPF_V3_LSTYPE_INTER_AREA_ROUTER     0x2004
126 #define OSPF_V3_LSTYPE_AS_EXTERNAL           0x4005
127 #define OSPF_V3_LSTYPE_GROUP_MEMBERSHIP      0x2006
128 #define OSPF_V3_LSTYPE_TYPE_7                0x2007
129 #define OSPF_V3_LSTYPE_LINK                  0x0008
130 #define OSPF_V3_LSTYPE_INTRA_AREA_PREFIX     0x2009
131
132 /* Opaque LSA types */
133 #define OSPF_LSTYPE_OP_LINKLOCAL 9
134 #define OSPF_LSTYPE_OP_AREALOCAL 10
135 #define OSPF_LSTYPE_OP_ASWIDE    11
136
137 #define OSPF_LINK_PTP           1
138 #define OSPF_LINK_TRANSIT       2
139 #define OSPF_LINK_STUB          3
140 #define OSPF_LINK_VIRTUAL       4
141
142 #define OSPF_V3_LINK_PTP        1
143 #define OSPF_V3_LINK_TRANSIT    2
144 #define OSPF_V3_LINK_RESERVED   3
145 #define OSPF_V3_LINK_VIRTUAL    4
146
147 #define OSPF_LSA_HEADER_LENGTH  20
148
149 /* Known opaque LSAs */
150 #define OSPF_LSA_MPLS_TE        1
151
152
153 static const value_string ls_type_vals[] = {
154         {OSPF_LSTYPE_ROUTER,                  "Router-LSA"                   },
155         {OSPF_LSTYPE_NETWORK,                 "Network-LSA"                  },
156         {OSPF_LSTYPE_SUMMERY,                 "Summary-LSA (IP network)"     },
157         {OSPF_LSTYPE_ASBR,                    "Summary-LSA (ASBR)"           },
158         {OSPF_LSTYPE_ASEXT,                   "AS-External-LSA (ASBR)"       },
159         {OSPF_LSTYPE_GRPMEMBER,               "Group Membership LSA"         },
160         {OSPF_LSTYPE_ASEXT7,                  "NSSA AS-External-LSA"         },
161         {OSPF_LSTYPE_EXTATTR,                 "External Attributes LSA"      },
162         {OSPF_LSTYPE_OP_LINKLOCAL,            "Opaque LSA, Link-local scope" },
163         {OSPF_LSTYPE_OP_AREALOCAL,            "Opaque LSA, Area-local scope" },
164         {0,                                   NULL                           }
165
166 };
167
168 static const value_string ls_opaque_type_vals[] = {
169         {OSPF_LSA_MPLS_TE, "Traffic Engineering LSA"                },
170         {2,                "Sycamore Optical Topology Descriptions" },
171         {3,                "grace-LSA"                              },
172         {0,                NULL                                     }
173 };
174
175 static const value_string v3_ls_type_vals[] = {
176         {OSPF_V3_LSTYPE_ROUTER,               "Router-LSA"                   },
177         {OSPF_V3_LSTYPE_NETWORK,              "Network-LSA"                  },
178         {OSPF_V3_LSTYPE_INTER_AREA_PREFIX,    "Inter-Area-Prefix-LSA"        },
179         {OSPF_V3_LSTYPE_INTER_AREA_ROUTER,    "Inter-Area-Router-LSA"        },
180         {OSPF_V3_LSTYPE_AS_EXTERNAL,          "AS-External-LSA"              },
181         {OSPF_V3_LSTYPE_GROUP_MEMBERSHIP,     "Group-Membership-LSA"         },
182         {OSPF_V3_LSTYPE_TYPE_7,               "Type-LSA"                     },
183         {OSPF_V3_LSTYPE_LINK,                 "Link-LSA"                     },
184         {OSPF_V3_LSTYPE_INTRA_AREA_PREFIX,    "Intra-Area-Prefix-LSA"        },
185         {0,                                   NULL                           }
186
187 };
188
189 static const value_string lls_tlv_type_vals[] = {
190         {1,                                   "Extended options TLV"         },
191         {2,                                   "Crypo Authentication TLV"     },
192         {0,                                   NULL                           },
193 };
194
195 static const value_string mpls_link_stlv_ltype_str[] = {
196     {1, "Point-to-point"},
197     {2, "Multi-access"},
198     {0, NULL},
199 };
200
201 #define OSPF_V2_ROUTER_LSA_FLAG_B 0x01
202 #define OSPF_V2_ROUTER_LSA_FLAG_E 0x02
203 #define OSPF_V2_ROUTER_LSA_FLAG_V 0x04
204 #define OSPF_V3_ROUTER_LSA_FLAG_B 0x01
205 #define OSPF_V3_ROUTER_LSA_FLAG_E 0x02
206 #define OSPF_V3_ROUTER_LSA_FLAG_V 0x04
207 #define OSPF_V3_ROUTER_LSA_FLAG_W 0x08
208
209 #define OSPF_V3_PREFIX_OPTION_NU 0x01
210 #define OSPF_V3_PREFIX_OPTION_LA 0x02
211 #define OSPF_V3_PREFIX_OPTION_MC 0x04
212 #define OSPF_V3_PREFIX_OPTION_P  0x08
213
214 #define OSPF_V3_AS_EXTERNAL_FLAG_T 0x01
215 #define OSPF_V3_AS_EXTERNAL_FLAG_F 0x02
216 #define OSPF_V3_AS_EXTERNAL_FLAG_E 0x04
217
218
219 static int proto_ospf = -1;
220
221 static gint ett_ospf = -1;
222 static gint ett_ospf_hdr = -1;
223 static gint ett_ospf_hello = -1;
224 static gint ett_ospf_desc = -1;
225 static gint ett_ospf_lsr = -1;
226 static gint ett_ospf_lsa = -1;
227 static gint ett_ospf_lsa_router_link = -1;
228 static gint ett_ospf_lsa_upd = -1;
229 static gint ett_ospf_v2_options = -1;
230 static gint ett_ospf_v3_options = -1;
231 static gint ett_ospf_dbd = -1;
232 static gint ett_ospf_lls_data_block = -1;
233 static gint ett_ospf_lls_tlv = -1;
234 static gint ett_ospf_lls_ext_options = -1;
235 static gint ett_ospf_v2_router_lsa_flags = -1;
236 static gint ett_ospf_v3_router_lsa_flags = -1;
237 static gint ett_ospf_v3_as_external_flags = -1;
238 static gint ett_ospf_v3_prefix_options = -1;
239
240 /* Trees for opaque LSAs */
241 static gint ett_ospf_lsa_mpls = -1;
242 static gint ett_ospf_lsa_mpls_router = -1;
243 static gint ett_ospf_lsa_mpls_link = -1;
244 static gint ett_ospf_lsa_mpls_link_stlv = -1;
245 static gint ett_ospf_lsa_mpls_link_stlv_admingrp = -1;
246 static gint ett_ospf_lsa_oif_tna = -1;
247 static gint ett_ospf_lsa_oif_tna_stlv = -1;
248
249
250
251 static const true_false_string tfs_v2_options_dc = {
252         "Demand Circuits are supported",
253         "Demand circuits are NOT supported"
254 };
255 static const true_false_string tfs_v2_options_l = {
256         "The packet contains LLS data block",
257         "The packet does NOT contain LLS data block"
258 };
259 static const true_false_string tfs_v2_options_np = {
260         "NSSA is supported",
261         "Nssa is NOT supported"
262 };
263 static const true_false_string tfs_v2_options_mc = {
264         "Multicast Capable",
265         "NOT multicast capable"
266 };
267 static const true_false_string tfs_v2_options_e = {
268         "ExternalRoutingCapability",
269         "NO ExternalRoutingCapability"
270 };
271 static const true_false_string tfs_v2_options_o = {
272         "O-bit is SET",
273         "O-bit is NOT set"
274 };
275 static const true_false_string tfs_v2_options_dn = {
276         "DN-bit is SET",
277         "DN-bit is NOT set"
278 };
279 static const true_false_string tfs_v3_options_v6 = {
280         "V6 is SET",
281         "V6 is NOT set"
282 };
283 static const true_false_string tfs_v3_options_e = {
284         "E is SET",
285         "E is NOT set"
286 };
287 static const true_false_string tfs_v3_options_mc = {
288         "MC is SET",
289         "MC is NOT set"
290 };
291 static const true_false_string tfs_v3_options_n = {
292         "N is SET",
293         "N is NOT set"
294 };
295 static const true_false_string tfs_v3_options_r = {
296         "R is SET",
297         "R is NOT set"
298 };
299 static const true_false_string tfs_v3_options_dc = {
300         "DC is SET",
301         "DC is NOT set"
302 };
303 static const true_false_string tfs_dbd_i = {
304         "Init bit is SET",
305         "Init bit is NOT set"
306 };
307 static const true_false_string tfs_dbd_m = {
308         "More bit is SET",
309         "More bit is NOT set"
310 };
311 static const true_false_string tfs_dbd_ms = {
312         "Master/Slave bit is SET",
313         "Master/Slave bit is NOT set"
314 };
315 static const true_false_string tfs_dbd_r = {
316         "OOBResync bit is SET",
317         "OOBResync bit is NOT set"
318 };
319 static const true_false_string tfs_lls_ext_options_lr = {
320         "LSDB Resynchrinization (LR-bit) is SET",
321         "LSDB Resynchrinization (LR-bit) is NOT set"
322 };
323 static const true_false_string tfs_lls_ext_options_rs = {
324         "Restart Signal (RS-bit) is SET",
325         "Restart Signal (RS-bit) is NOT set"
326 };
327 static const true_false_string tfs_v2_router_lsa_flags_b = {
328         "Area border router",
329         "NO Area border router"
330 };
331 static const true_false_string tfs_v2_router_lsa_flags_e = {
332         "AS boundary router",
333         "NO AS boundary router"
334 };
335 static const true_false_string tfs_v2_router_lsa_flags_v = {
336         "Virtual link endpoint",
337         "NO Virtual link endpoint"
338 };
339 static const true_false_string tfs_v3_router_lsa_flags_b = {
340         "Area border router",
341         "NO Area border router"
342 };
343 static const true_false_string tfs_v3_router_lsa_flags_e = {
344         "AS boundary router",
345         "NO AS boundary router"
346 };
347 static const true_false_string tfs_v3_router_lsa_flags_v = {
348         "Virtual link endpoint",
349         "NO Virtual link endpoint"
350 };
351 static const true_false_string tfs_v3_router_lsa_flags_w = {
352         "Wild-card multicast receiver",
353         "NO Wild-card multicast receiver"
354 };
355 static const true_false_string tfs_v3_as_external_flags_t = {
356         "External Route Tag is included",
357         "External Route Tag is NOT included"
358 };
359 static const true_false_string tfs_v3_as_external_flags_f = {
360         "Forwarding Address is included",
361         "Forwarding Address is NOT included"
362 };
363 static const true_false_string tfs_v3_as_external_flags_e = {
364         "Type 2 external metric",
365         "Type 1 external metric"
366 };
367 static const true_false_string tfs_v3_prefix_options_nu = {
368         "NoUnicast capability bit is SET",
369         "NoUnicast capability bit is NOT set"
370 };
371 static const true_false_string tfs_v3_prefix_options_la = {
372         "LocalAddress capability bit is SET",
373         "LocalAddress capability bit is NOT set"
374 };
375 static const true_false_string tfs_v3_prefix_options_mc = {
376         "Multicast capability bit is SET",
377         "Multicast capability bit is NOT set"
378 };
379 static const true_false_string tfs_v3_prefix_options_p = {
380         "Propagate bit is SET",
381         "Propagate bit is NOT set"
382 };
383
384 /*-----------------------------------------------------------------------
385  * OSPF Filtering
386  *-----------------------------------------------------------------------*/
387
388 /* The OSPF filtering keys */
389 enum {
390
391     OSPFF_MSG_TYPE,
392
393     OSPFF_MSG_MIN,
394     OSPFF_MSG_HELLO,
395     OSPFF_MSG_DB_DESC,
396     OSPFF_MSG_LS_REQ,
397     OSPFF_MSG_LS_UPD,
398     OSPFF_MSG_LS_ACK,
399
400     OSPFF_LS_TYPE,
401     OSPFF_LS_OPAQUE_TYPE,
402
403     OSPFF_LS_MPLS_TE_INSTANCE,
404
405     OSPFF_LS_MIN,
406     OSPFF_LS_ROUTER,
407     OSPFF_LS_NETWORK,
408     OSPFF_LS_SUMMARY,
409     OSPFF_LS_ASBR,
410     OSPFF_LS_ASEXT,
411     OSPFF_LS_GRPMEMBER,
412     OSPFF_LS_ASEXT7,
413     OSPFF_LS_EXTATTR,
414     OSPFF_LS_OPAQUE,
415
416     OSPFF_SRC_ROUTER,
417     OSPFF_ADV_ROUTER,
418     OSPFF_LS_MPLS,
419     OSPFF_LS_MPLS_ROUTERID,
420
421     OSPFF_LS_MPLS_LINKTYPE,
422     OSPFF_LS_MPLS_LINKID,
423     OSPFF_LS_MPLS_LOCAL_ADDR,
424     OSPFF_LS_MPLS_REMOTE_ADDR,
425     OSPFF_LS_MPLS_LOCAL_IFID,
426     OSPFF_LS_MPLS_REMOTE_IFID,
427     OSPFF_LS_MPLS_LINKCOLOR,
428
429     OSPFF_V2_OPTIONS,
430     OSPFF_V2_OPTIONS_E,
431     OSPFF_V2_OPTIONS_MC,
432     OSPFF_V2_OPTIONS_NP,
433     OSPFF_V2_OPTIONS_L,
434     OSPFF_V2_OPTIONS_DC,
435     OSPFF_V2_OPTIONS_O,
436     OSPFF_V2_OPTIONS_DN,
437     OSPFF_V3_OPTIONS,
438     OSPFF_V3_OPTIONS_V6,
439     OSPFF_V3_OPTIONS_E,
440     OSPFF_V3_OPTIONS_MC,
441     OSPFF_V3_OPTIONS_N,
442     OSPFF_V3_OPTIONS_R,
443     OSPFF_V3_OPTIONS_DC,
444     OSPFF_DBD,
445     OSPFF_DBD_R,
446     OSPFF_DBD_I,
447     OSPFF_DBD_M,
448     OSPFF_DBD_MS,
449     OSPFF_LLS_EXT_OPTIONS,
450     OSPFF_LLS_EXT_OPTIONS_LR,
451     OSPFF_LLS_EXT_OPTIONS_RS,
452     OSPFF_V2_ROUTER_LSA_FLAG,
453     OSPFF_V2_ROUTER_LSA_FLAG_B,
454     OSPFF_V2_ROUTER_LSA_FLAG_E,
455     OSPFF_V2_ROUTER_LSA_FLAG_V,
456     OSPFF_V3_ROUTER_LSA_FLAG,
457     OSPFF_V3_ROUTER_LSA_FLAG_B,
458     OSPFF_V3_ROUTER_LSA_FLAG_E,
459     OSPFF_V3_ROUTER_LSA_FLAG_V,
460     OSPFF_V3_ROUTER_LSA_FLAG_W,
461     OSPFF_V3_AS_EXTERNAL_FLAG,
462     OSPFF_V3_AS_EXTERNAL_FLAG_T,
463     OSPFF_V3_AS_EXTERNAL_FLAG_F,
464     OSPFF_V3_AS_EXTERNAL_FLAG_E,
465     OSPFF_V3_PREFIX_OPTION,
466     OSPFF_V3_PREFIX_OPTION_NU,
467     OSPFF_V3_PREFIX_OPTION_LA,
468     OSPFF_V3_PREFIX_OPTION_MC,
469     OSPFF_V3_PREFIX_OPTION_P,
470
471     OSPFF_MAX
472 };
473
474 static int ospf_filter[OSPFF_MAX];
475
476 static hf_register_info ospff_info[] = {
477
478     /* Message type number */
479     {&ospf_filter[OSPFF_MSG_TYPE],
480      { "Message Type", "ospf.msg", FT_UINT8, BASE_DEC, VALS(pt_vals), 0x0,
481         "", HFILL }},
482
483     /* Message types */
484     {&ospf_filter[OSPFF_MSG_HELLO],
485      { "Hello", "ospf.msg.hello", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
486         "", HFILL }},
487     {&ospf_filter[OSPFF_MSG_DB_DESC],
488      { "Database Description", "ospf.msg.dbdesc", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
489         "", HFILL }},
490     {&ospf_filter[OSPFF_MSG_LS_REQ],
491      { "Link State Adv Request", "ospf.msg.lsreq", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
492         "", HFILL }},
493     {&ospf_filter[OSPFF_MSG_LS_UPD],
494      { "Link State Adv Update", "ospf.msg.lsupdate", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
495         "", HFILL }},
496     {&ospf_filter[OSPFF_MSG_LS_ACK],
497      { "Link State Adv Acknowledgement", "ospf.msg.lsack", FT_BOOLEAN,
498        BASE_NONE, NULL, 0x0, "", HFILL }},
499
500
501
502     /* LS Types */
503     {&ospf_filter[OSPFF_LS_TYPE],
504      { "Link-State Advertisement Type", "ospf.lsa", FT_UINT8, BASE_DEC,
505        VALS(ls_type_vals), 0x0, "", HFILL }},
506     {&ospf_filter[OSPFF_LS_OPAQUE_TYPE],
507      { "Link State ID Opaque Type", "ospf.lsid_opaque_type", FT_UINT8, BASE_DEC,
508        VALS(ls_opaque_type_vals), 0x0, "", HFILL }},
509
510     {&ospf_filter[OSPFF_LS_MPLS_TE_INSTANCE],
511      { "Link State ID TE-LSA Instance", "ospf.lsid_te_lsa.instance", FT_UINT16, BASE_DEC,
512        NULL, 0x0, "", HFILL }},
513
514     {&ospf_filter[OSPFF_LS_ROUTER],
515      { "Router LSA", "ospf.lsa.router", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
516         "", HFILL }},
517     {&ospf_filter[OSPFF_LS_NETWORK],
518      { "Network LSA", "ospf.lsa.network", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
519         "", HFILL }},
520     {&ospf_filter[OSPFF_LS_SUMMARY],
521      { "Summary LSA (IP Network)", "ospf.lsa.summary", FT_BOOLEAN, BASE_NONE,
522        NULL, 0x0, "", HFILL }},
523     {&ospf_filter[OSPFF_LS_ASBR],
524      { "Summary LSA (ASBR)", "ospf.lsa.asbr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
525         "", HFILL }},
526     {&ospf_filter[OSPFF_LS_ASEXT],
527      { "AS-External LSA (ASBR)", "ospf.lsa.asext", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
528         "", HFILL }},
529     {&ospf_filter[OSPFF_LS_GRPMEMBER],
530      { "Group Membership LSA", "ospf.lsa.member", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
531         "", HFILL }},
532     {&ospf_filter[OSPFF_LS_ASEXT7],
533      { "NSSA AS-External LSA", "ospf.lsa.nssa", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
534         "", HFILL }},
535     {&ospf_filter[OSPFF_LS_EXTATTR],
536      { "External Attributes LSA", "ospf.lsa.attr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
537         "", HFILL }},
538     {&ospf_filter[OSPFF_LS_OPAQUE],
539      { "Opaque LSA", "ospf.lsa.opaque", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
540         "", HFILL }},
541
542     /* Other interesting OSPF values */
543
544     {&ospf_filter[OSPFF_SRC_ROUTER],
545      { "Source OSPF Router", "ospf.srcrouter", FT_IPv4, BASE_NONE, NULL, 0x0,
546        "", HFILL }},
547
548     {&ospf_filter[OSPFF_ADV_ROUTER],
549      { "Advertising Router", "ospf.advrouter", FT_IPv4, BASE_NONE, NULL, 0x0,
550        "", HFILL }},
551
552    {&ospf_filter[OSPFF_LS_MPLS],
553      { "MPLS Traffic Engineering LSA", "ospf.lsa.mpls", FT_BOOLEAN,
554        BASE_NONE, NULL, 0x0, "", HFILL }},
555
556     {&ospf_filter[OSPFF_LS_MPLS_ROUTERID],
557      { "MPLS/TE Router ID", "ospf.mpls.routerid", FT_IPv4, BASE_NONE, NULL, 0x0,
558        "", HFILL }},
559
560     {&ospf_filter[OSPFF_LS_MPLS_LINKTYPE],
561      { "MPLS/TE Link Type", "ospf.mpls.linktype", FT_UINT8, BASE_DEC, VALS(mpls_link_stlv_ltype_str), 0x0,
562        "MPLS/TE Link Type", HFILL }},
563     {&ospf_filter[OSPFF_LS_MPLS_LINKID],
564      { "MPLS/TE Link ID", "ospf.mpls.linkid", FT_IPv4, BASE_NONE, NULL, 0x0,
565        "", HFILL }},
566     {&ospf_filter[OSPFF_LS_MPLS_LOCAL_ADDR],
567      { "MPLS/TE Local Interface Address", "ospf.mpls.local_addr", FT_IPv4,
568        BASE_NONE, NULL, 0x0, "", HFILL }},
569     {&ospf_filter[OSPFF_LS_MPLS_REMOTE_ADDR],
570      { "MPLS/TE Remote Interface Address", "ospf.mpls.remote_addr", FT_IPv4,
571        BASE_NONE, NULL, 0x0, "", HFILL }},
572     {&ospf_filter[OSPFF_LS_MPLS_LOCAL_IFID],
573      { "MPLS/TE Local Interface Index", "ospf.mpls.local_id", FT_UINT32,
574        BASE_DEC, NULL, 0x0, "", HFILL }},
575     {&ospf_filter[OSPFF_LS_MPLS_REMOTE_IFID],
576      { "MPLS/TE Remote Interface Index", "ospf.mpls.remote_id", FT_UINT32,
577        BASE_DEC, NULL, 0x0, "", HFILL }},
578     {&ospf_filter[OSPFF_LS_MPLS_LINKCOLOR],
579      { "MPLS/TE Link Resource Class/Color", "ospf.mpls.linkcolor", FT_UINT32,
580        BASE_HEX, NULL, 0x0, "MPLS/TE Link Resource Class/Color", HFILL }},
581
582     {&ospf_filter[OSPFF_V2_OPTIONS],
583      { "Options", "ospf.v2.options", FT_UINT8, BASE_HEX,
584        NULL, 0x0, "", HFILL }},
585     {&ospf_filter[OSPFF_V2_OPTIONS_E],
586      { "E", "ospf.v2.options.e", FT_BOOLEAN, 8,
587        TFS(&tfs_v2_options_e), OSPF_V2_OPTIONS_E, "", HFILL }},
588     {&ospf_filter[OSPFF_V2_OPTIONS_MC],
589      { "MC", "ospf.v2.options.mc", FT_BOOLEAN, 8,
590        TFS(&tfs_v2_options_mc), OSPF_V2_OPTIONS_MC, "", HFILL }},
591     {&ospf_filter[OSPFF_V2_OPTIONS_NP],
592      { "NP", "ospf.v2.options.np", FT_BOOLEAN, 8,
593        TFS(&tfs_v2_options_np), OSPF_V2_OPTIONS_NP, "", HFILL }},
594     {&ospf_filter[OSPFF_V2_OPTIONS_L],
595      { "L", "ospf.v2.options.l", FT_BOOLEAN, 8,
596        TFS(&tfs_v2_options_l), OSPF_V2_OPTIONS_L, "", HFILL }},
597     {&ospf_filter[OSPFF_V2_OPTIONS_DC],
598      { "DC", "ospf.v2.options.dc", FT_BOOLEAN, 8,
599        TFS(&tfs_v2_options_dc), OSPF_V2_OPTIONS_DC, "", HFILL }},
600     {&ospf_filter[OSPFF_V2_OPTIONS_O],
601      { "O", "ospf.v2.options.o", FT_BOOLEAN, 8,
602        TFS(&tfs_v2_options_o), OSPF_V2_OPTIONS_O, "", HFILL }},
603     {&ospf_filter[OSPFF_V2_OPTIONS_DN],
604      { "DN", "ospf.v2.options.dn", FT_BOOLEAN, 8,
605        TFS(&tfs_v2_options_dn), OSPF_V2_OPTIONS_DN, "", HFILL }},
606     {&ospf_filter[OSPFF_V3_OPTIONS],
607      { "Options", "ospf.v3.options", FT_UINT24, BASE_HEX,
608        NULL, 0x0, "", HFILL }},
609     {&ospf_filter[OSPFF_V3_OPTIONS_V6],
610      { "V6", "ospf.v3.options.v6", FT_BOOLEAN, 24,
611        TFS(&tfs_v3_options_v6), OSPF_V3_OPTIONS_V6, "", HFILL }},
612     {&ospf_filter[OSPFF_V3_OPTIONS_E],
613      { "E", "ospf.v3.options.e", FT_BOOLEAN, 24,
614        TFS(&tfs_v3_options_e), OSPF_V3_OPTIONS_E, "", HFILL }},
615     {&ospf_filter[OSPFF_V3_OPTIONS_MC],
616      { "MC", "ospf.v3.options.mc", FT_BOOLEAN, 24,
617        TFS(&tfs_v3_options_mc), OSPF_V3_OPTIONS_MC, "", HFILL }},
618     {&ospf_filter[OSPFF_V3_OPTIONS_N],
619      { "N", "ospf.v3.options.n", FT_BOOLEAN, 24,
620        TFS(&tfs_v3_options_n), OSPF_V3_OPTIONS_N, "", HFILL }},
621     {&ospf_filter[OSPFF_V3_OPTIONS_R],
622      { "R", "ospf.v3.options.r", FT_BOOLEAN, 24,
623        TFS(&tfs_v3_options_r), OSPF_V3_OPTIONS_R, "", HFILL }},
624     {&ospf_filter[OSPFF_V3_OPTIONS_DC],
625      { "DC", "ospf.v3.options.dc", FT_BOOLEAN, 24,
626        TFS(&tfs_v3_options_dc), OSPF_V3_OPTIONS_DC, "", HFILL }},
627     {&ospf_filter[OSPFF_DBD],
628      { "DB Description", "ospf.dbd", FT_UINT8, BASE_HEX,
629        NULL, 0x0, "", HFILL }},
630     {&ospf_filter[OSPFF_DBD_R],
631      { "R", "ospf.dbd.r", FT_BOOLEAN, 8,
632        TFS(&tfs_dbd_r), OSPF_DBD_FLAG_R, "", HFILL }},
633     {&ospf_filter[OSPFF_DBD_I],
634      { "I", "ospf.dbd.i", FT_BOOLEAN, 8,
635        TFS(&tfs_dbd_i), OSPF_DBD_FLAG_I, "", HFILL }},
636     {&ospf_filter[OSPFF_DBD_M],
637      { "M", "ospf.dbd.m", FT_BOOLEAN, 8,
638        TFS(&tfs_dbd_m), OSPF_DBD_FLAG_M, "", HFILL }},
639     {&ospf_filter[OSPFF_DBD_MS],
640      { "MS", "ospf.dbd.ms", FT_BOOLEAN, 8,
641        TFS(&tfs_dbd_ms), OSPF_DBD_FLAG_MS, "", HFILL }},
642     {&ospf_filter[OSPFF_LLS_EXT_OPTIONS],
643      { "Options", "ospf.lls.ext.options", FT_UINT32, BASE_HEX,
644        NULL, 0x0, "", HFILL }},
645     {&ospf_filter[OSPFF_LLS_EXT_OPTIONS_LR],
646      { "LR", "ospf.lls.ext.options.lr", FT_BOOLEAN, 32,
647        TFS(&tfs_lls_ext_options_lr), OSPF_LLS_EXT_OPTIONS_LR, "", HFILL }},
648     {&ospf_filter[OSPFF_LLS_EXT_OPTIONS_RS],
649      { "RS", "ospf.lls.ext.options.rs", FT_BOOLEAN, 32,
650        TFS(&tfs_lls_ext_options_rs), OSPF_LLS_EXT_OPTIONS_RS, "", HFILL }},
651     {&ospf_filter[OSPFF_V2_ROUTER_LSA_FLAG],
652      { "Flags", "ospf.v2.router.lsa.flags", FT_UINT8, BASE_HEX,
653        NULL, 0x0, "", HFILL }},
654     {&ospf_filter[OSPFF_V2_ROUTER_LSA_FLAG_B],
655      { "B", "ospf.v2.router.lsa.flags.b", FT_BOOLEAN, 8,
656        TFS(&tfs_v2_router_lsa_flags_b), OSPF_V2_ROUTER_LSA_FLAG_B, "", HFILL }},
657     {&ospf_filter[OSPFF_V2_ROUTER_LSA_FLAG_E],
658      { "E", "ospf.v2.router.lsa.flags.e", FT_BOOLEAN, 8,
659        TFS(&tfs_v2_router_lsa_flags_e), OSPF_V2_ROUTER_LSA_FLAG_E, "", HFILL }},
660     {&ospf_filter[OSPFF_V2_ROUTER_LSA_FLAG_V],
661      { "V", "ospf.v2.router.lsa.flags.v", FT_BOOLEAN, 8,
662        TFS(&tfs_v2_router_lsa_flags_v), OSPF_V2_ROUTER_LSA_FLAG_V, "", HFILL }},
663     {&ospf_filter[OSPFF_V3_ROUTER_LSA_FLAG],
664      { "Flags", "ospf.v3.router.lsa.flags", FT_UINT8, BASE_HEX,
665        NULL, 0x0, "", HFILL }},
666     {&ospf_filter[OSPFF_V3_ROUTER_LSA_FLAG_B],
667      { "B", "ospf.v3.router.lsa.flags.b", FT_BOOLEAN, 8,
668        TFS(&tfs_v3_router_lsa_flags_b), OSPF_V3_ROUTER_LSA_FLAG_B, "", HFILL }},
669     {&ospf_filter[OSPFF_V3_ROUTER_LSA_FLAG_E],
670      { "E", "ospf.v3.router.lsa.flags.e", FT_BOOLEAN, 8,
671        TFS(&tfs_v3_router_lsa_flags_e), OSPF_V3_ROUTER_LSA_FLAG_E, "", HFILL }},
672     {&ospf_filter[OSPFF_V3_ROUTER_LSA_FLAG_V],
673      { "V", "ospf.v3.router.lsa.flags.v", FT_BOOLEAN, 8,
674        TFS(&tfs_v3_router_lsa_flags_v), OSPF_V3_ROUTER_LSA_FLAG_V, "", HFILL }},
675     {&ospf_filter[OSPFF_V3_ROUTER_LSA_FLAG_W],
676      { "W", "ospf.v3.router.lsa.flags.w", FT_BOOLEAN, 8,
677        TFS(&tfs_v3_router_lsa_flags_w), OSPF_V3_ROUTER_LSA_FLAG_W, "", HFILL }},
678     {&ospf_filter[OSPFF_V3_AS_EXTERNAL_FLAG],
679      { "Flags", "ospf.v3.as.external.flags", FT_UINT8, BASE_HEX,
680        NULL, 0x0, "", HFILL }},
681     {&ospf_filter[OSPFF_V3_AS_EXTERNAL_FLAG_T],
682      { "T", "ospf.v3.as.external.flags.t", FT_BOOLEAN, 8,
683        TFS(&tfs_v3_as_external_flags_t), OSPF_V3_AS_EXTERNAL_FLAG_T, "", HFILL }},
684     {&ospf_filter[OSPFF_V3_AS_EXTERNAL_FLAG_F],
685      { "F", "ospf.v3.as.external.flags.f", FT_BOOLEAN, 8,
686        TFS(&tfs_v3_as_external_flags_f), OSPF_V3_AS_EXTERNAL_FLAG_F, "", HFILL }},
687     {&ospf_filter[OSPFF_V3_AS_EXTERNAL_FLAG_E],
688      { "E", "ospf.v3.as.external.flags.e", FT_BOOLEAN, 8,
689        TFS(&tfs_v3_as_external_flags_e), OSPF_V3_AS_EXTERNAL_FLAG_E, "", HFILL }},
690     {&ospf_filter[OSPFF_V3_PREFIX_OPTION],
691      { "PrefixOptions", "ospf.v3.prefix.options", FT_UINT8, BASE_HEX,
692        NULL, 0x0, "", HFILL }},
693     {&ospf_filter[OSPFF_V3_PREFIX_OPTION_NU],
694      { "NU", "ospf.v3.prefix.options.nu", FT_BOOLEAN, 8,
695        TFS(&tfs_v3_prefix_options_nu), OSPF_V3_PREFIX_OPTION_NU, "", HFILL }},
696     {&ospf_filter[OSPFF_V3_PREFIX_OPTION_LA],
697      { "LA", "ospf.v3.prefix.options.la", FT_BOOLEAN, 8,
698        TFS(&tfs_v3_prefix_options_la), OSPF_V3_PREFIX_OPTION_LA, "", HFILL }},
699     {&ospf_filter[OSPFF_V3_PREFIX_OPTION_MC],
700      { "MC", "ospf.v3.prefix.options.mc", FT_BOOLEAN, 8,
701        TFS(&tfs_v3_prefix_options_mc), OSPF_V3_PREFIX_OPTION_MC, "", HFILL }},
702     {&ospf_filter[OSPFF_V3_PREFIX_OPTION_P],
703      { "P", "ospf.v3.prefix.options.p", FT_BOOLEAN, 8,
704        TFS(&tfs_v3_prefix_options_p), OSPF_V3_PREFIX_OPTION_P, "", HFILL }},
705 };
706
707 static guint8 ospf_msg_type_to_filter (guint8 msg_type)
708 {
709     if (msg_type >= OSPF_HELLO &&
710         msg_type <= OSPF_LS_ACK)
711         return msg_type + OSPFF_MSG_MIN;
712     return -1;
713 }
714
715 static guint8 ospf_ls_type_to_filter (guint8 ls_type)
716 {
717     if (ls_type >= OSPF_LSTYPE_ROUTER &&
718         ls_type <= OSPF_LSTYPE_EXTATTR)
719         return OSPFF_LS_MIN + ls_type;
720     else if (ls_type >= OSPF_LSTYPE_OP_LINKLOCAL &&
721              ls_type <= OSPF_LSTYPE_OP_ASWIDE)
722         return OSPFF_LS_OPAQUE;
723     else
724         return -1;
725 }
726
727 typedef struct _bitfield_info {
728     int         hfindex;
729     gint        *ett;
730     int         *index;
731     int         num;
732 } bitfield_info;
733
734 static int bf_dbd[] = {
735     OSPFF_DBD_R,
736     OSPFF_DBD_I,
737     OSPFF_DBD_M,
738     OSPFF_DBD_MS
739 };
740 static int bf_lls_ext_options[] = {
741     OSPFF_LLS_EXT_OPTIONS_RS,
742     OSPFF_LLS_EXT_OPTIONS_LR
743 };
744 static int bf_v2_router_lsa_flags[] = {
745     OSPFF_V2_ROUTER_LSA_FLAG_V,
746     OSPFF_V2_ROUTER_LSA_FLAG_E,
747     OSPFF_V2_ROUTER_LSA_FLAG_B
748 };
749 static int bf_v3_router_lsa_flags[] = {
750     OSPFF_V3_ROUTER_LSA_FLAG_W,
751     OSPFF_V3_ROUTER_LSA_FLAG_V,
752     OSPFF_V3_ROUTER_LSA_FLAG_E,
753     OSPFF_V3_ROUTER_LSA_FLAG_B
754 };
755 static int bf_v3_as_external_flags[] = {
756     OSPFF_V3_AS_EXTERNAL_FLAG_E,
757     OSPFF_V3_AS_EXTERNAL_FLAG_F,
758     OSPFF_V3_AS_EXTERNAL_FLAG_T
759 };
760 static int bf_v2_options[] = {
761     OSPFF_V2_OPTIONS_DN,
762     OSPFF_V2_OPTIONS_O,
763     OSPFF_V2_OPTIONS_DC,
764     OSPFF_V2_OPTIONS_L,
765     OSPFF_V2_OPTIONS_NP,
766     OSPFF_V2_OPTIONS_MC,
767     OSPFF_V2_OPTIONS_E
768 };
769 static int bf_v3_options[] = {
770     OSPFF_V3_OPTIONS_DC,
771     OSPFF_V3_OPTIONS_R,
772     OSPFF_V3_OPTIONS_N,
773     OSPFF_V3_OPTIONS_MC,
774     OSPFF_V3_OPTIONS_E,
775     OSPFF_V3_OPTIONS_V6
776 };
777 static int bf_v3_prefix_options[] = {
778     OSPFF_V3_PREFIX_OPTION_P,
779     OSPFF_V3_PREFIX_OPTION_MC,
780     OSPFF_V3_PREFIX_OPTION_LA,
781     OSPFF_V3_PREFIX_OPTION_NU
782 };
783
784 static bitfield_info bfinfo_dbd = {
785     OSPFF_DBD, &ett_ospf_dbd,
786     bf_dbd, array_length(bf_dbd)
787 };
788 static bitfield_info bfinfo_lls_ext_options = {
789     OSPFF_LLS_EXT_OPTIONS, &ett_ospf_lls_ext_options,
790     bf_lls_ext_options, array_length(bf_lls_ext_options)
791 };
792 static bitfield_info bfinfo_v2_router_lsa_flags = {
793     OSPFF_V2_ROUTER_LSA_FLAG, &ett_ospf_v2_router_lsa_flags,
794     bf_v2_router_lsa_flags, array_length(bf_v2_router_lsa_flags)
795 };
796 static bitfield_info bfinfo_v3_router_lsa_flags = {
797     OSPFF_V3_ROUTER_LSA_FLAG, &ett_ospf_v3_router_lsa_flags,
798     bf_v3_router_lsa_flags, array_length(bf_v3_router_lsa_flags)
799 };
800 static bitfield_info bfinfo_v3_as_external_flags = {
801     OSPFF_V3_AS_EXTERNAL_FLAG, &ett_ospf_v3_as_external_flags,
802     bf_v3_as_external_flags, array_length(bf_v3_as_external_flags)
803 };
804 static bitfield_info bfinfo_v2_options = {
805     OSPFF_V2_OPTIONS, &ett_ospf_v2_options,
806     bf_v2_options, array_length(bf_v2_options)
807 };
808 static bitfield_info bfinfo_v3_options = {
809     OSPFF_V3_OPTIONS, &ett_ospf_v3_options,
810     bf_v3_options, array_length(bf_v3_options)
811 };
812 static bitfield_info bfinfo_v3_prefix_options = {
813     OSPFF_V3_PREFIX_OPTION, &ett_ospf_v3_prefix_options,
814     bf_v3_prefix_options, array_length(bf_v3_prefix_options)
815 };
816
817 #define MAX_OPTIONS_LEN 128
818 static void
819 dissect_ospf_bitfield (proto_tree *parent_tree, tvbuff_t *tvb, int offset,
820                         bitfield_info *bfinfo)
821 {
822     proto_item *item = NULL;
823     proto_tree *tree = NULL;
824     guint32 flags;
825     char *str;
826     gint length, pos, i;
827     header_field_info *hfinfo;
828     int hfindex, index;
829
830     hfindex = ospf_filter[bfinfo->hfindex];
831     hfinfo = proto_registrar_get_nth(hfindex);
832     switch (hfinfo->type) {
833         case FT_UINT8:
834             flags = tvb_get_guint8(tvb, offset);
835             length = 1;
836             break;
837         case FT_UINT16:
838             flags = tvb_get_ntohs(tvb, offset);
839             length = 2;
840             break;
841         case FT_UINT24:
842             flags = tvb_get_ntoh24(tvb, offset);
843             length = 3;
844             break;
845         case FT_UINT32:
846             flags = tvb_get_ntohl(tvb, offset);
847             length = 4;
848             break;
849         default:
850             return;
851     }
852
853     if (parent_tree) {
854         item = proto_tree_add_uint(parent_tree, hfindex, tvb, offset, length, flags);
855         tree = proto_item_add_subtree(item, *bfinfo->ett);
856
857         str = ep_alloc(MAX_OPTIONS_LEN);
858         str[0] = 0;
859         for (i = 0, pos = 0; i < bfinfo->num; i++) {
860             index = ospf_filter[bfinfo->index[i]];
861             hfinfo = proto_registrar_get_nth(index);
862             if (flags & hfinfo->bitmask) {
863                 pos += g_snprintf(str+pos, MAX_OPTIONS_LEN-pos, "%s%s",
864                                   pos ? ", " : "",
865                                   hfinfo->name);
866             }
867             proto_tree_add_boolean(tree, index, tvb, offset, length, flags);
868         }
869         proto_item_append_text(item, " (%s)", str);
870     }
871 }
872
873 static dissector_handle_t data_handle;
874
875 static void dissect_ospf_hello(tvbuff_t*, int, proto_tree*, guint8, guint16);
876 static void dissect_ospf_db_desc(tvbuff_t*, int, proto_tree*, guint8, guint16);
877 static void dissect_ospf_ls_req(tvbuff_t*, int, proto_tree*, guint8, guint16);
878 static void dissect_ospf_ls_upd(tvbuff_t*, int, proto_tree*, guint8, guint16);
879 static void dissect_ospf_ls_ack(tvbuff_t*, int, proto_tree*, guint8, guint16);
880 static void dissect_ospf_lls_data_block(tvbuff_t*, int, proto_tree*, guint8);
881
882 /* dissect_ospf_v[23]lsa returns the offset of the next LSA
883  * if disassemble_body is set to FALSE (e.g. in LSA ACK
884  * packets), the offset is set to the offset of the next
885  * LSA header
886  */
887 static int dissect_ospf_v2_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body);
888 static int dissect_ospf_v3_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body);
889
890 static void dissect_ospf_v3_address_prefix(tvbuff_t *, int, int, proto_tree *);
891
892 static int 
893 ospf_has_lls_block(tvbuff_t *tvb, int offset, guint8 packet_type)
894 {
895     guint8 flags;
896
897     /* LLS block can be found only in HELLO and DBDESC packets */
898     switch (packet_type) {
899     case OSPF_HELLO:
900         flags = tvb_get_guint8 (tvb, offset + 6);
901         return flags & OSPF_V2_OPTIONS_L;
902     case OSPF_DB_DESC:
903         flags = tvb_get_guint8 (tvb, offset + 2);
904         return flags & OSPF_V2_OPTIONS_L;
905     }
906
907     return 0;
908 }
909
910 static void
911 dissect_ospf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
912 {
913     proto_tree *ospf_tree = NULL;
914     proto_item *ti;
915     proto_tree *ospf_header_tree;
916     guint8  version;
917     guint8  packet_type;
918     guint16 ospflen;
919     vec_t cksum_vec[4];
920     int cksum_vec_len;
921     guint32 phdr[2];
922     guint16 cksum, computed_cksum;
923     guint length, reported_length;
924     guint16 auth_type;
925     char auth_data[8+1];
926     int crypto_len = 0;
927     unsigned int ospf_header_length;
928     guint8 instance_ID;
929     guint8 reserved;
930     guint32 areaid;
931
932
933     if (check_col(pinfo->cinfo, COL_PROTOCOL))
934         col_set_str(pinfo->cinfo, COL_PROTOCOL, "OSPF");
935     if (check_col(pinfo->cinfo, COL_INFO))
936         col_clear(pinfo->cinfo, COL_INFO);
937
938     version = tvb_get_guint8(tvb, 0);
939     switch (version) {
940         case OSPF_VERSION_2:
941             ospf_header_length = OSPF_VERSION_2_HEADER_LENGTH;
942             break;
943         case OSPF_VERSION_3:
944             ospf_header_length = OSPF_VERSION_3_HEADER_LENGTH;
945             break;
946         default:
947             ospf_header_length = 14;
948             break;
949     }
950
951     packet_type = tvb_get_guint8(tvb, 1);
952     if (check_col(pinfo->cinfo, COL_INFO)) {
953         col_add_str(pinfo->cinfo, COL_INFO,
954                     val_to_str(packet_type, pt_vals, "Unknown (%u)"));
955     }
956
957     if (tree) {
958         ospflen = tvb_get_ntohs(tvb, 2);
959
960         ti = proto_tree_add_item(tree, proto_ospf, tvb, 0, -1, FALSE);
961         ospf_tree = proto_item_add_subtree(ti, ett_ospf);
962
963         ti = proto_tree_add_text(ospf_tree, tvb, 0, ospf_header_length,
964                                  "OSPF Header");
965         ospf_header_tree = proto_item_add_subtree(ti, ett_ospf_hdr);
966
967         proto_tree_add_text(ospf_header_tree, tvb, 0, 1, "OSPF Version: %u",
968                             version);
969         proto_tree_add_item(ospf_header_tree, ospf_filter[OSPFF_MSG_TYPE],
970                             tvb, 1, 1, FALSE);
971         proto_tree_add_item_hidden(ospf_header_tree,
972                                    ospf_filter[ospf_msg_type_to_filter(packet_type)],
973                                    tvb, 1, 1, FALSE);
974         proto_tree_add_text(ospf_header_tree, tvb, 2, 2, "Packet Length: %u",
975                             ospflen);
976         proto_tree_add_item(ospf_header_tree, ospf_filter[OSPFF_SRC_ROUTER],
977                             tvb, 4, 4, FALSE);
978         areaid=tvb_get_ntohl(tvb,8);
979         proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: %s%s",
980                                ip_to_str(tvb_get_ptr(tvb, 8, 4)), areaid == 0 ? " (Backbone)" : "");
981
982         /*
983          * Quit at this point if it's an unknown OSPF version.
984          */
985         switch (version) {
986
987         case OSPF_VERSION_2:
988         case OSPF_VERSION_3:
989             break;
990
991         default:
992             cksum = tvb_get_ntohs(tvb, 12);
993             if (cksum == 0) {
994                 /* No checksum supplied in the packet. */
995                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
996                     "Packet Checksum: 0x%04x (none)", cksum);
997             } else {
998                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
999                     "Packet Checksum: 0x%04x", cksum);
1000             }
1001             proto_tree_add_text(ospf_tree, tvb, 14, -1,
1002                 "Unknown OSPF version %u", version);
1003             return;
1004         }
1005
1006         cksum = tvb_get_ntohs(tvb, 12);
1007         length = tvb_length(tvb);
1008         /* XXX - include only the length from the OSPF header? */
1009         reported_length = tvb_reported_length(tvb);
1010         if (cksum == 0) {
1011             /* No checksum supplied in the packet. */
1012             proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
1013                 "Packet Checksum: 0x%04x (none)", cksum);
1014         } else if (!pinfo->fragmented && length >= reported_length
1015                 && length >= ospf_header_length) {
1016             /* The packet isn't part of a fragmented datagram and isn't
1017                truncated, so we can checksum it. */
1018
1019             switch (version) {
1020
1021             case OSPF_VERSION_2:
1022                 /* Header, not including the authentication data (the OSPFv2
1023                    checksum excludes the 64-bit authentication field). */
1024                 cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, 16);
1025                 cksum_vec[0].len = 16;
1026                 if (length > ospf_header_length) {
1027                     /* Rest of the packet, again not including the
1028                        authentication data. */
1029                     reported_length -= ospf_header_length;
1030                     cksum_vec[1].ptr = tvb_get_ptr(tvb, ospf_header_length, reported_length);
1031                     cksum_vec[1].len = reported_length;
1032                     cksum_vec_len = 2;
1033                 } else {
1034                     /* There's nothing but a header. */
1035                     cksum_vec_len = 1;
1036                 }
1037                 break;
1038
1039             case OSPF_VERSION_3:
1040                 /* IPv6-style checksum, covering the entire OSPF packet
1041                    and a prepended IPv6 pseudo-header. */
1042
1043                 /* Set up the fields of the pseudo-header. */
1044                 cksum_vec[0].ptr = pinfo->src.data;
1045                 cksum_vec[0].len = pinfo->src.len;
1046                 cksum_vec[1].ptr = pinfo->dst.data;
1047                 cksum_vec[1].len = pinfo->dst.len;
1048                 cksum_vec[2].ptr = (const guint8 *)&phdr;
1049                 phdr[0] = g_htonl(ospflen);
1050                 phdr[1] = g_htonl(IP_PROTO_OSPF);
1051                 cksum_vec[2].len = 8;
1052
1053                 cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, reported_length);
1054                 cksum_vec[3].len = reported_length;
1055                 cksum_vec_len = 4;
1056                 break;
1057
1058             default:
1059                 DISSECTOR_ASSERT_NOT_REACHED();
1060                 cksum_vec_len = 0;
1061                 break;
1062             }
1063             computed_cksum = in_cksum(cksum_vec, cksum_vec_len);
1064             if (computed_cksum == 0) {
1065                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
1066                         "Packet Checksum: 0x%04x [correct]", cksum);
1067             } else {
1068                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
1069                         "Packet Checksum: 0x%04x [incorrect, should be 0x%04x]",
1070                         cksum, in_cksum_shouldbe(cksum, computed_cksum));
1071             }
1072         } else {
1073             proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
1074                 "Packet Checksum: 0x%04x", cksum);
1075         }
1076
1077
1078         switch (version) {
1079
1080         case OSPF_VERSION_2:
1081             /* Authentication is only valid for OSPFv2 */
1082             auth_type = tvb_get_ntohs(tvb, 14);
1083             proto_tree_add_text(ospf_header_tree, tvb, 14, 2, "Auth Type: %s",
1084                             val_to_str(auth_type, auth_vals, "Unknown (%u)"));
1085             switch (auth_type) {
1086
1087             case OSPF_AUTH_NONE:
1088                 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (none)");
1089                 break;
1090
1091             case OSPF_AUTH_SIMPLE:
1092                 tvb_get_nstringz0(tvb, 16, 8+1, auth_data);
1093                 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data: %s", auth_data);
1094                 break;
1095
1096             case OSPF_AUTH_CRYPT:
1097                 proto_tree_add_text(ospf_header_tree, tvb, 18, 1, "Auth Key ID: %u",
1098                                 tvb_get_guint8(tvb, 18));
1099                 crypto_len = tvb_get_guint8(tvb, 19);
1100                 proto_tree_add_text(ospf_header_tree, tvb, 19, 1, "Auth Data Length: %u",
1101                                 crypto_len);
1102                 proto_tree_add_text(ospf_header_tree, tvb, 20, 4, "Auth Crypto Sequence Number: 0x%x",
1103                                 tvb_get_ntohl(tvb, 20));
1104
1105                 /* Show the message digest that was appended to the end of the
1106                    OSPF message - but only if it's present (we don't want
1107                    to get an exception before we've tried dissecting OSPF
1108                    message). */
1109                 if (tvb_bytes_exist(tvb, ospflen, crypto_len)) {
1110                     proto_tree_add_text(ospf_header_tree, tvb, ospflen, crypto_len,
1111                                     "Auth Data: %s",
1112                                     tvb_bytes_to_str(tvb, ospflen, crypto_len));
1113                 }
1114                 break;
1115
1116             default:
1117                 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (unknown)");
1118                 break;
1119             }
1120             break;
1121
1122         case OSPF_VERSION_3:
1123             /* Instance ID and "reserved" is OSPFv3-only */
1124             instance_ID = tvb_get_guint8(tvb, 14);
1125             proto_tree_add_text(ospf_header_tree, tvb, 14, 1, "Instance ID: %u",
1126                             instance_ID);
1127             reserved = tvb_get_guint8(tvb, 15);
1128             proto_tree_add_text(ospf_header_tree, tvb, 15, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),
1129                                 reserved);
1130             break;
1131         }
1132
1133         switch (packet_type){
1134
1135         case OSPF_HELLO:
1136             dissect_ospf_hello(tvb, ospf_header_length, ospf_tree, version, 
1137                             ospflen - ospf_header_length);
1138             break;
1139
1140         case OSPF_DB_DESC:
1141             dissect_ospf_db_desc(tvb, ospf_header_length, ospf_tree, version, 
1142                             ospflen - ospf_header_length);
1143             break;
1144
1145         case OSPF_LS_REQ:
1146             dissect_ospf_ls_req(tvb, ospf_header_length, ospf_tree, version, 
1147                             ospflen - ospf_header_length);
1148             break;
1149
1150         case OSPF_LS_UPD:
1151             dissect_ospf_ls_upd(tvb, ospf_header_length, ospf_tree, version, 
1152                             ospflen - ospf_header_length);
1153             break;
1154
1155         case OSPF_LS_ACK:
1156             dissect_ospf_ls_ack(tvb, ospf_header_length, ospf_tree, version, 
1157                             ospflen - ospf_header_length);
1158             break;
1159
1160         default:
1161             call_dissector(data_handle,
1162                 tvb_new_subset(tvb, ospf_header_length, -1, -1), pinfo, tree);
1163             break;
1164         }
1165
1166         /* take care of the LLS data block */
1167         if (ospf_has_lls_block(tvb, ospf_header_length, packet_type))
1168             dissect_ospf_lls_data_block(tvb, ospflen + crypto_len, ospf_tree, 
1169                             version);
1170     }
1171 }
1172
1173 static int
1174 dissect_ospf_lls_tlv(tvbuff_t *tvb, int offset, proto_tree *tree)
1175 {
1176     proto_item *ti;
1177     proto_tree *ospf_lls_tlv_tree;
1178     guint16 type;
1179     guint16 length;
1180
1181     type = tvb_get_ntohs(tvb, offset);
1182     length = tvb_get_ntohs(tvb, offset + 2);
1183
1184     ti = proto_tree_add_text(tree, tvb, offset, length + 4, 
1185                     val_to_str(type, lls_tlv_type_vals, "Unknown TLV"));
1186     ospf_lls_tlv_tree = proto_item_add_subtree(ti, ett_ospf_lls_tlv);
1187     
1188     proto_tree_add_text(ospf_lls_tlv_tree, tvb, offset, 2,
1189                     "Type: %d", type);
1190     proto_tree_add_text(ospf_lls_tlv_tree, tvb, offset + 2, 2,
1191                     "Length: %d", length);
1192       
1193     switch(type) {
1194         case 1:
1195             dissect_ospf_bitfield(ospf_lls_tlv_tree, tvb, offset + 4, &bfinfo_lls_ext_options);
1196             break;
1197         case 2:
1198             proto_tree_add_text(ospf_lls_tlv_tree, tvb, offset + 4, 4, 
1199                             "Sequence number 0x%08x", 
1200                             tvb_get_ntohl(tvb, offset + 4));
1201             proto_tree_add_text(ospf_lls_tlv_tree, tvb, offset + 8, length - 4,
1202                             "Auth Data: %s", 
1203                             tvb_bytes_to_str(tvb, offset + 8, length - 4));
1204             break;
1205     }
1206
1207     return offset + length + 4;
1208 }
1209
1210 static void
1211 dissect_ospf_lls_data_block(tvbuff_t *tvb, int offset, proto_tree *tree, 
1212                 guint8 version)
1213 {
1214     proto_tree *ospf_lls_data_block_tree;
1215     proto_item *ti;
1216     guint16 ospf_lls_len;
1217     int orig_offset = offset;
1218
1219     ospf_lls_len = tvb_get_ntohs(tvb, offset + 2);
1220     ti = proto_tree_add_text(tree, tvb, offset, -1, "OSPF LLS Data Block");
1221     ospf_lls_data_block_tree = proto_item_add_subtree(ti, 
1222                     ett_ospf_lls_data_block);
1223
1224     if (version != OSPF_VERSION_2)
1225             return;
1226
1227     /* TODO: verify checksum */
1228     proto_tree_add_text(ospf_lls_data_block_tree, tvb, offset, 2, 
1229                     "Checksum: 0x%04x", tvb_get_ntohs(tvb, offset));
1230     proto_tree_add_text(ospf_lls_data_block_tree, tvb, offset + 2, 2,
1231                     "LLS Data Length: %d bytes", ospf_lls_len * 4);
1232     
1233     offset += 4;
1234     while (orig_offset + ospf_lls_len * 4 > offset)
1235         offset = dissect_ospf_lls_tlv (tvb, offset, ospf_lls_data_block_tree);
1236 }
1237
1238 static void
1239 dissect_ospf_hello(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version, 
1240                 guint16 length)
1241 {
1242     proto_tree *ospf_hello_tree;
1243     proto_item *ti;
1244     int orig_offset = offset;
1245
1246     ti = proto_tree_add_text(tree, tvb, offset, length, "OSPF Hello Packet");
1247     ospf_hello_tree = proto_item_add_subtree(ti, ett_ospf_hello);
1248
1249     switch (version ) {
1250         case OSPF_VERSION_2:
1251             proto_tree_add_text(ospf_hello_tree, tvb, offset, 4, "Network Mask: %s",
1252                         ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1253             proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 2,
1254                         "Hello Interval: %u seconds",
1255                         tvb_get_ntohs(tvb, offset + 4));
1256
1257             dissect_ospf_bitfield(ospf_hello_tree, tvb, offset + 6, &bfinfo_v2_options);
1258             proto_tree_add_text(ospf_hello_tree, tvb, offset + 7, 1, "Router Priority: %u",
1259                         tvb_get_guint8(tvb, offset + 7));
1260             proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 4, "Router Dead Interval: %u seconds",
1261                         tvb_get_ntohl(tvb, offset + 8));
1262             proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
1263                         ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
1264             proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
1265                         ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
1266
1267             offset += 20;
1268             while (orig_offset + length > offset) {
1269                 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
1270                             "Active Neighbor: %s",
1271                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1272                 offset += 4;
1273             }
1274             break;
1275         case OSPF_VERSION_3:
1276             proto_tree_add_text(ospf_hello_tree, tvb, offset + 0, 4, "Interface ID: %u",
1277                         tvb_get_ntohl(tvb, offset + 0));
1278             proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 1, "Router Priority: %u",
1279                         tvb_get_guint8(tvb, offset + 4));
1280             dissect_ospf_bitfield(ospf_hello_tree, tvb, offset + 5, &bfinfo_v3_options);
1281             proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 2,
1282                         "Hello Interval: %u seconds",
1283                         tvb_get_ntohs(tvb, offset + 8));
1284             proto_tree_add_text(ospf_hello_tree, tvb, offset + 10, 2, "Router Dead Interval: %u seconds",
1285                         tvb_get_ntohs(tvb, offset + 10));
1286             proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
1287                         ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
1288             proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
1289                         ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
1290             offset += 20;
1291             while (orig_offset + length > offset) {
1292                 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
1293                             "Active Neighbor: %s",
1294                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1295                 offset += 4;
1296             }
1297
1298             break;
1299     }
1300 }
1301
1302 static void
1303 dissect_ospf_db_desc(tvbuff_t *tvb, int offset, proto_tree *tree, 
1304                 guint8 version, guint16 length)
1305 {
1306     proto_tree *ospf_db_desc_tree=NULL;
1307     proto_item *ti;
1308     guint8 reserved;
1309     int orig_offset = offset;
1310
1311     if (tree) {
1312         ti = proto_tree_add_text(tree, tvb, offset, length, "OSPF DB Description");
1313         ospf_db_desc_tree = proto_item_add_subtree(ti, ett_ospf_desc);
1314
1315         switch (version ) {
1316
1317             case OSPF_VERSION_2:
1318                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 2, "Interface MTU: %u",
1319                             tvb_get_ntohs(tvb, offset));
1320
1321                 dissect_ospf_bitfield(ospf_db_desc_tree, tvb, offset + 2, &bfinfo_v2_options);
1322                 dissect_ospf_bitfield(ospf_db_desc_tree, tvb, offset + 3, &bfinfo_dbd);
1323
1324                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 4, "DD Sequence: %u",
1325                             tvb_get_ntohl(tvb, offset + 4));
1326
1327                 offset += 8;
1328                 break;
1329
1330             case OSPF_VERSION_3:
1331
1332                 reserved = tvb_get_guint8(tvb, offset);
1333                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),
1334                                 reserved);
1335
1336                 dissect_ospf_bitfield(ospf_db_desc_tree, tvb, offset + 1, &bfinfo_v3_options);
1337
1338                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 2, "Interface MTU: %u",
1339                             tvb_get_ntohs(tvb, offset+4));
1340
1341                 reserved = tvb_get_guint8(tvb, offset + 6);
1342                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 6, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),
1343                                 reserved);
1344
1345                 dissect_ospf_bitfield(ospf_db_desc_tree, tvb, offset + 7, &bfinfo_dbd);
1346
1347                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 8, 4, "DD Sequence: %u",
1348                             tvb_get_ntohl(tvb, offset + 8));
1349
1350                 offset += 12;
1351                 break;
1352         }
1353     }
1354
1355     /* LS Headers will be processed here */
1356     /* skip to the end of DB-Desc header */
1357     while (orig_offset + length > offset) {
1358       if ( version == OSPF_VERSION_2)
1359           offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE);
1360       else
1361           if ( version == OSPF_VERSION_3)
1362               offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE);
1363     }
1364
1365 }
1366
1367 static void
1368 dissect_ospf_ls_req(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version,
1369                 guint16 length)
1370 {
1371     proto_tree *ospf_lsr_tree;
1372     proto_item *ti;
1373     guint32 ls_type;
1374     guint16 reserved;
1375     int orig_offset = offset;
1376
1377     /* zero or more LS requests may be within a LS Request */
1378     /* we place every request for a LSA in a single subtree */
1379     while (orig_offset + length > offset) {
1380         ti = proto_tree_add_text(tree, tvb, offset, OSPF_LS_REQ_LENGTH,
1381                                  "Link State Request");
1382         ospf_lsr_tree = proto_item_add_subtree(ti, ett_ospf_lsr);
1383
1384         switch ( version ) {
1385
1386             case OSPF_VERSION_2:
1387                 ls_type = tvb_get_ntohl(tvb, offset);
1388                 proto_tree_add_item(ospf_lsr_tree, ospf_filter[OSPFF_LS_TYPE],
1389                                     tvb, offset, 4, FALSE);
1390                 break;
1391             case OSPF_VERSION_3:
1392                 reserved = tvb_get_ntohs(tvb, offset);
1393                 proto_tree_add_text(ospf_lsr_tree, tvb, offset, 2,
1394                     (reserved == 0 ? "Reserved: %u" :  "Reserved: %u [incorrect, should be 0]"), reserved);
1395                 ls_type = tvb_get_ntohs(tvb, offset+2);
1396                 proto_tree_add_text(ospf_lsr_tree, tvb, offset+2, 2, "LS Type: %s (0x%04x)",
1397                             val_to_str(ls_type, v3_ls_type_vals, "Unknown"),
1398                             ls_type);
1399                 break;
1400         }
1401
1402
1403         proto_tree_add_text(ospf_lsr_tree, tvb, offset + 4, 4, "Link State ID: %s",
1404                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
1405         proto_tree_add_item(ospf_lsr_tree, ospf_filter[OSPFF_ADV_ROUTER],
1406                             tvb, offset + 8, 4, FALSE);
1407
1408         offset += 12;
1409     }
1410 }
1411
1412 static void
1413 dissect_ospf_ls_upd(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version,
1414                 guint16 length)
1415 {
1416     proto_tree *ospf_lsa_upd_tree=NULL;
1417     proto_item *ti;
1418     guint32 lsa_nr;
1419     guint32 lsa_counter;
1420
1421     ti = proto_tree_add_text(tree, tvb, offset, length, "LS Update Packet");
1422     ospf_lsa_upd_tree = proto_item_add_subtree(ti, ett_ospf_lsa_upd);
1423
1424     lsa_nr = tvb_get_ntohl(tvb, offset);
1425     proto_tree_add_text(ospf_lsa_upd_tree, tvb, offset, 4, "Number of LSAs: %u",
1426                         lsa_nr);
1427     /* skip to the beginning of the first LSA */
1428     offset += 4; /* the LS Upd Packet contains only a 32 bit #LSAs field */
1429
1430     lsa_counter = 0;
1431     while (lsa_counter < lsa_nr) {
1432         if ( version == OSPF_VERSION_2)
1433             offset = dissect_ospf_v2_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
1434         else
1435             if ( version == OSPF_VERSION_3)
1436                 offset = dissect_ospf_v3_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
1437         lsa_counter += 1;
1438     }
1439 }
1440
1441 static void
1442 dissect_ospf_ls_ack(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version,
1443                 guint16 length)
1444 {
1445     int orig_offset = offset;
1446     /* the body of a LS Ack packet simply contains zero or more LSA Headers */
1447     while (orig_offset + length > offset) {
1448         if ( version == OSPF_VERSION_2)
1449             offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE);
1450         else
1451             if ( version == OSPF_VERSION_3)
1452               offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE);
1453     }
1454 }
1455
1456 /*
1457  * Returns if an LSA is opaque, i.e. requires special treatment
1458  */
1459 static int
1460 is_opaque(int lsa_type)
1461 {
1462     return (lsa_type >= OSPF_LSTYPE_OP_LINKLOCAL &&
1463         lsa_type <= OSPF_LSTYPE_OP_ASWIDE);
1464 }
1465
1466 /* MPLS/TE TLV types */
1467 #define MPLS_TLV_ROUTER    1
1468 #define MPLS_TLV_LINK      2
1469 #define OIF_TLV_TNA    32768
1470
1471 /* MPLS/TE Link STLV types */
1472 enum {
1473     MPLS_LINK_TYPE       = 1,
1474     MPLS_LINK_ID,
1475     MPLS_LINK_LOCAL_IF,
1476     MPLS_LINK_REMOTE_IF,
1477     MPLS_LINK_TE_METRIC,
1478     MPLS_LINK_MAX_BW,
1479     MPLS_LINK_MAX_RES_BW,
1480     MPLS_LINK_UNRES_BW,
1481     MPLS_LINK_COLOR,
1482     MPLS_LINK_LOCAL_REMOTE_ID = 11,
1483     MPLS_LINK_PROTECTION = 14,
1484     MPLS_LINK_IF_SWITCHING_DESC,
1485     MPLS_LINK_SHARED_RISK_GROUP
1486 };
1487
1488 /* OIF TLV types */
1489 enum {
1490     OIF_LOCAL_NODE_ID = 32773,
1491     OIF_REMOTE_NODE_ID,
1492     OIF_SONET_SDH_SWITCHING_CAPABILITY,
1493     OIF_TNA_IPv4_ADDRESS,
1494     OIF_NODE_ID,
1495     OIF_TNA_IPv6_ADDRESS,
1496     OIF_TNA_NSAP_ADDRESS
1497 };
1498
1499 static const value_string mpls_link_stlv_str[] = {
1500     {MPLS_LINK_TYPE, "Link Type"},
1501     {MPLS_LINK_ID, "Link ID"},
1502     {MPLS_LINK_LOCAL_IF, "Local Interface IP Address"},
1503     {MPLS_LINK_REMOTE_IF, "Remote Interface IP Address"},
1504     {MPLS_LINK_TE_METRIC, "Traffic Engineering Metric"},
1505     {MPLS_LINK_MAX_BW, "Maximum Bandwidth"},
1506     {MPLS_LINK_MAX_RES_BW, "Maximum Reservable Bandwidth"},
1507     {MPLS_LINK_UNRES_BW, "Unreserved Bandwidth"},
1508     {MPLS_LINK_COLOR, "Resource Class/Color"},
1509     {MPLS_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier"},
1510     {MPLS_LINK_PROTECTION, "Link Protection Type"},
1511     {MPLS_LINK_IF_SWITCHING_DESC, "Interface Switching Capability Descriptor"},
1512     {MPLS_LINK_SHARED_RISK_GROUP, "Shared Risk Link Group"},
1513     {OIF_LOCAL_NODE_ID, "Local Node ID"},
1514     {OIF_REMOTE_NODE_ID, "Remote Node ID"},
1515     {OIF_SONET_SDH_SWITCHING_CAPABILITY, "Sonet/SDH Interface Switching Capability"},
1516     {0, NULL},
1517 };
1518
1519 static const value_string oif_stlv_str[] = {
1520     {OIF_TNA_IPv4_ADDRESS, "TNA address"},
1521     {OIF_NODE_ID, "Node ID"},
1522     {OIF_TNA_IPv6_ADDRESS, "TNA address"},
1523     {OIF_TNA_NSAP_ADDRESS, "TNA address"},
1524     {0, NULL},
1525 };
1526
1527 /*
1528  * Dissect MPLS/TE opaque LSA
1529  */
1530 static void
1531 dissect_ospf_lsa_mpls(tvbuff_t *tvb, int offset, proto_tree *tree,
1532                       guint32 length)
1533 {
1534     proto_item *ti;
1535     proto_tree *mpls_tree;
1536     proto_tree *tlv_tree;
1537     proto_tree *stlv_tree;
1538     proto_tree *stlv_admingrp_tree = NULL;
1539
1540     int tlv_type;
1541     int tlv_length;
1542     int tlv_end_offset;
1543
1544     int stlv_type, stlv_len, stlv_offset;
1545     const char *stlv_name;
1546     guint32 stlv_admingrp, mask;
1547     int i;
1548     guint8 switch_cap;
1549
1550     ti = proto_tree_add_text(tree, tvb, offset, length,
1551                              "MPLS Traffic Engineering LSA");
1552     proto_tree_add_item_hidden(tree, ospf_filter[OSPFF_LS_MPLS],
1553                                tvb, offset, 2, FALSE);
1554     mpls_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls);
1555
1556     while (length != 0) {
1557         tlv_type = tvb_get_ntohs(tvb, offset);
1558         tlv_length = tvb_get_ntohs(tvb, offset + 2);
1559         tlv_end_offset = offset + tlv_length + 4;
1560
1561         switch (tlv_type) {
1562
1563         case MPLS_TLV_ROUTER:
1564             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
1565                                      "Router Address: %s",
1566                                      ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
1567             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_router);
1568             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 1 - Router Address");
1569             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
1570                                 tlv_length);
1571             proto_tree_add_item(tlv_tree, ospf_filter[OSPFF_LS_MPLS_ROUTERID],
1572                                 tvb, offset+4, 4, FALSE);
1573             break;
1574
1575         case MPLS_TLV_LINK:
1576             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
1577                                      "Link Information");
1578             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
1579             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 2 - Link Information");
1580             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
1581                                 tlv_length);
1582             stlv_offset = offset + 4;
1583
1584             /* Walk down the sub-TLVs for link information */
1585             while (stlv_offset < tlv_end_offset) {
1586                 stlv_type = tvb_get_ntohs(tvb, stlv_offset);
1587                 stlv_len = tvb_get_ntohs(tvb, stlv_offset + 2);
1588                 stlv_name = val_to_str(stlv_type, mpls_link_stlv_str, "Unknown sub-TLV");
1589                 switch (stlv_type) {
1590
1591                 case MPLS_LINK_TYPE:
1592                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1593                                      "%s: %u - %s", stlv_name,
1594                                      tvb_get_guint8(tvb, stlv_offset + 4),
1595                                      val_to_str(tvb_get_guint8(tvb, stlv_offset + 4), 
1596                                         mpls_link_stlv_ltype_str, "Unknown Link Type"));
1597                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1598                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1599                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1600                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1601                                         stlv_len);
1602                     proto_tree_add_item(stlv_tree, ospf_filter[OSPFF_LS_MPLS_LINKTYPE],
1603                                         tvb, stlv_offset+4, 1,FALSE);
1604                     break;
1605
1606                 case MPLS_LINK_ID:
1607                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1608                                              "%s: %s", stlv_name,
1609                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1610                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1611                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1612                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1613                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1614                                         stlv_len);
1615                     proto_tree_add_item(stlv_tree, ospf_filter[OSPFF_LS_MPLS_LINKID],
1616                                         tvb, stlv_offset+4, 4, FALSE);
1617                     break;
1618
1619                 case MPLS_LINK_LOCAL_IF:
1620                 case MPLS_LINK_REMOTE_IF:
1621                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1622                                              "%s", stlv_name);
1623                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1624                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1625                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1626                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1627                                         stlv_len);
1628                     /*   The Local/Remote Interface IP Address sub-TLV is TLV type 3/4, and is 4N
1629                        octets in length, where N is the number of neighbor addresses. */
1630                     for (i=0; i < stlv_len; i+=4)
1631                       proto_tree_add_item(stlv_tree,
1632                                           stlv_type==MPLS_LINK_LOCAL_IF ?
1633                                           ospf_filter[OSPFF_LS_MPLS_LOCAL_ADDR] :
1634                                           ospf_filter[OSPFF_LS_MPLS_REMOTE_ADDR],
1635                                           tvb, stlv_offset+4+i, 4, FALSE);
1636                     break;
1637
1638                 case MPLS_LINK_TE_METRIC:
1639                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1640                                              "%s: %u", stlv_name,
1641                                              tvb_get_ntohl(tvb, stlv_offset + 4));
1642                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1643                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1644                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1645                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1646                                         stlv_len);
1647                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %u", stlv_name,
1648                                         tvb_get_ntohl(tvb, stlv_offset + 4));
1649                     break;
1650
1651                 case MPLS_LINK_COLOR:
1652                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1653                                              "%s: 0x%08x", stlv_name,
1654                                              tvb_get_ntohl(tvb, stlv_offset + 4));
1655                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1656                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1657                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1658                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1659                                         stlv_len);
1660                     stlv_admingrp = tvb_get_ntohl(tvb, stlv_offset + 4);
1661                     mask = 1;
1662                     ti = proto_tree_add_item(stlv_tree, ospf_filter[OSPFF_LS_MPLS_LINKCOLOR],
1663                                         tvb, stlv_offset+4, 4, FALSE);
1664                     stlv_admingrp_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv_admingrp);
1665                     if (stlv_admingrp_tree == NULL)
1666                         return;
1667                     for (i = 0 ; i < 32 ; i++) {
1668                         if ((stlv_admingrp & mask) != 0) {
1669                             proto_tree_add_text(stlv_admingrp_tree, tvb, stlv_offset+4,
1670                                 4, "Group %d", i);
1671                         }
1672                         mask <<= 1;
1673                     }
1674                     break;
1675
1676                 case MPLS_LINK_MAX_BW:
1677                 case MPLS_LINK_MAX_RES_BW:
1678                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1679                                              "%s: %.10g bytes/s (%.0f bits/s)", stlv_name,
1680                                              tvb_get_ntohieee_float(tvb, stlv_offset + 4),
1681                                              tvb_get_ntohieee_float(tvb, stlv_offset + 4) * 8.0);
1682                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1683                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1684                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1685                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1686                                         stlv_len);
1687                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %.10g bytes/s (%.0f bits/s)", stlv_name,
1688                                         tvb_get_ntohieee_float(tvb, stlv_offset + 4),
1689                                         tvb_get_ntohieee_float(tvb, stlv_offset + 4) * 8.0);
1690                     break;
1691
1692                 case MPLS_LINK_UNRES_BW:
1693                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1694                                              "%s", stlv_name);
1695                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1696                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1697                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1698                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1699                                         stlv_len);
1700                     for (i = 0; i < 8; i++) {
1701                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+(i*4), 4,
1702                                             "Pri %d: %.10g bytes/s (%.0f bits/s)", i,
1703                                             tvb_get_ntohieee_float(tvb, stlv_offset + 4 + i*4),
1704                                             tvb_get_ntohieee_float(tvb, stlv_offset + 4 + i*4) * 8.0);
1705                     }
1706                     break;
1707
1708                 case MPLS_LINK_LOCAL_REMOTE_ID:
1709                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1710                                              "%s: %d (0x%x) - %d (0x%x)", stlv_name,
1711                                              tvb_get_ntohl(tvb, stlv_offset + 4),
1712                                              tvb_get_ntohl(tvb, stlv_offset + 4),
1713                                              tvb_get_ntohl(tvb, stlv_offset + 8),
1714                                              tvb_get_ntohl(tvb, stlv_offset + 8));
1715                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1716                     
1717                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1718                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1719                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1720                                         stlv_len);                      
1721                     proto_tree_add_item(stlv_tree,
1722                                         ospf_filter[OSPFF_LS_MPLS_LOCAL_IFID],
1723                                         tvb, stlv_offset+4, 4, FALSE);
1724                     proto_tree_add_item(stlv_tree,
1725                                         ospf_filter[OSPFF_LS_MPLS_REMOTE_IFID],
1726                                         tvb, stlv_offset+8, 4, FALSE);
1727                     break;
1728
1729                 case MPLS_LINK_IF_SWITCHING_DESC:
1730                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1731                                              "%s", stlv_name);
1732                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1733                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1734                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1735                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1736                                         stlv_len);
1737                     switch_cap = tvb_get_guint8 (tvb, stlv_offset+4);
1738                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Switching Type: %s",
1739                                         val_to_str(tvb_get_guint8(tvb,stlv_offset+4),
1740                                                    gmpls_switching_type_str, "Unknown (%d)"));
1741                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+5, 1, "Encoding: %s",
1742                                         val_to_str(tvb_get_guint8(tvb,stlv_offset+5),
1743                                                    gmpls_lsp_enc_str, "Unknown (%d)"));
1744                     for (i = 0; i < 8; i++) {
1745                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+8+(i*4), 4,
1746                                             "Pri %d: %.10g bytes/s (%.0f bits/s)", i,
1747                                             tvb_get_ntohieee_float(tvb, stlv_offset + 8 + i*4),
1748                                             tvb_get_ntohieee_float(tvb, stlv_offset + 8 + i*4) * 8.0);
1749                     }
1750                     if (switch_cap >=1 && switch_cap <=4) {           /* PSC-1 .. PSC-4 */
1751                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+40, 4,
1752                                             "Minimum LSP bandwidth: %.10g bytes/s (%.0f bits/s)",
1753                                             tvb_get_ntohieee_float(tvb, stlv_offset + 40),
1754                                             tvb_get_ntohieee_float(tvb, stlv_offset + 40) * 8.0);
1755                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+44, 2,
1756                                             "Interface MTU: %d", tvb_get_ntohs(tvb, stlv_offset+44));
1757                     }
1758
1759                     if (switch_cap == 100) {                         /* TDM */
1760                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+40, 4,
1761                                             "Minimum LSP bandwidth: %.10g bytes/s (%.0f bits/s)",
1762                                             tvb_get_ntohieee_float(tvb, stlv_offset + 40),
1763                                             tvb_get_ntohieee_float(tvb, stlv_offset + 40) * 8.0);
1764                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+44, 2,
1765                                             "SONET/SDH: %s",
1766                                             tvb_get_guint8(tvb, stlv_offset+44) ?
1767                                             "Arbitrary" : "Standard");
1768                     }
1769                     break;
1770                 case MPLS_LINK_PROTECTION:
1771                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1772                                              "%s", stlv_name);
1773                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1774                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1775                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1776                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1777                                         stlv_len);
1778                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Protection Capability: %s (0x%x)",
1779                                         val_to_str(tvb_get_guint8(tvb,stlv_offset+4), gmpls_protection_cap_str, "Unknown (%d)"),tvb_get_guint8(tvb,stlv_offset+4));
1780                     break;
1781                 
1782                 case MPLS_LINK_SHARED_RISK_GROUP:
1783                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1784                                              "%s", stlv_name);
1785                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1786                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1787                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1788                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1789                                         stlv_len);
1790                     for (i=0; i < stlv_len; i+=4)
1791                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+i, 4, "Shared Risk Link Group: %u", 
1792                                         tvb_get_ntohl(tvb,stlv_offset+4+i)); 
1793                     break;
1794
1795                 case OIF_LOCAL_NODE_ID:
1796                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1797                                              "%s: %s", stlv_name,
1798                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1799                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1800                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1801                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1802                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1803                                         stlv_len);
1804                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "Local Node ID: %s",
1805                                         ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1806                     break;
1807
1808                 case OIF_REMOTE_NODE_ID:
1809                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1810                                              "%s: %s", stlv_name,
1811                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1812                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1813                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1814                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1815                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1816                                         stlv_len);
1817                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "Remote Node ID: %s",
1818                                         ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1819                     break;
1820
1821                 case OIF_SONET_SDH_SWITCHING_CAPABILITY:
1822                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4, "%s", stlv_name);
1823                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1824                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1825                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1826                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1827                                         stlv_len);
1828                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Switching Cap: %s",
1829                                         val_to_str(tvb_get_guint8 (tvb, stlv_offset+4),
1830                                                    gmpls_switching_type_str, "Unknown (%d)"));
1831                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+5, 1, "Encoding: %s",
1832                                         val_to_str(tvb_get_guint8(tvb,stlv_offset+5),
1833                                                    gmpls_lsp_enc_str, "Unknown (%d)"));
1834                     for (i = 0; i < (stlv_len - 4) / 4; i++) {
1835                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+8+(i*4), 4,
1836                                             "%s: %d free timeslots",
1837                                             val_to_str(tvb_get_guint8(tvb, stlv_offset+8+(i*4)),
1838                                                        gmpls_sonet_signal_type_str,
1839                                                        "Unknown Signal Type (%d)"),
1840                                             tvb_get_ntoh24(tvb, stlv_offset + 9 + i*4));
1841                     }
1842
1843                     break;
1844                 default:
1845                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1846                                         "Unknown Link sub-TLV: %u", stlv_type);
1847                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1848                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1849                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1850                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1851                                         stlv_len);
1852                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, stlv_len,
1853                                         "TLV Value");
1854                     break;
1855                 }
1856                 stlv_offset += ((stlv_len+4+3)/4)*4;
1857             }
1858             break;
1859
1860         case OIF_TLV_TNA:
1861             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
1862                                      "TNA Information");
1863             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_oif_tna);
1864             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 32768 - TNA Information");
1865             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
1866                                 tlv_length);
1867             stlv_offset = offset + 4;
1868
1869             /* Walk down the sub-TLVs for TNA information */
1870             while (stlv_offset < tlv_end_offset) {
1871                 stlv_type = tvb_get_ntohs(tvb, stlv_offset);
1872                 stlv_len = tvb_get_ntohs(tvb, stlv_offset + 2);
1873                 stlv_name = val_to_str(stlv_type, oif_stlv_str, "Unknown sub-TLV");
1874                 switch (stlv_type) {
1875
1876                 case OIF_NODE_ID:
1877                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1878                                              "%s: %s", stlv_name,
1879                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1880                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_oif_tna_stlv);
1881                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1882                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1883                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1884                                         stlv_len);
1885                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %s", stlv_name,
1886                                         ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1887                     break;
1888
1889                 case OIF_TNA_IPv4_ADDRESS:
1890                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1891                                              "%s (IPv4): %s", stlv_name,
1892                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 8, 4)));
1893                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_oif_tna_stlv);
1894                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1895                                         "TLV Type: %u: %s (IPv4)", stlv_type, stlv_name);
1896                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u", stlv_len);
1897                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Addr Length: %u",
1898                                         tvb_get_guint8 (tvb, stlv_offset+4));
1899                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+8, stlv_len - 4, "TNA Addr: %s",
1900                                         ip_to_str(tvb_get_ptr(tvb, stlv_offset + 8, 4)));
1901                     break;
1902
1903                 case OIF_TNA_IPv6_ADDRESS:
1904                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1905                                              "%s (IPv6): %s", stlv_name,
1906                                              ip6_to_str((const struct e_in6_addr *)
1907                                                          tvb_get_ptr(tvb, stlv_offset + 8, 16)));
1908                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_oif_tna_stlv);
1909                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1910                                         "TLV Type: %u: %s (IPv6)", stlv_type, stlv_name);
1911                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u", stlv_len);
1912                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Addr Length: %u",
1913                                         tvb_get_guint8 (tvb, stlv_offset+4));
1914                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+8, stlv_len - 4, "TNA Addr: %s",
1915                                         ip6_to_str((const struct e_in6_addr *)
1916                                                     tvb_get_ptr(tvb, stlv_offset + 8, 16)));
1917                     break;
1918
1919                 case OIF_TNA_NSAP_ADDRESS:
1920                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1921                                              "%s (NSAP): %s", stlv_name,
1922                                              tvb_bytes_to_str (tvb, stlv_offset + 8, stlv_len - 4));
1923                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_oif_tna_stlv);
1924                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1925                                         "TLV Type: %u: %s (NSAP)", stlv_type, stlv_name);
1926                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u", stlv_len);
1927                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Addr Length: %u",
1928                                             tvb_get_guint8 (tvb, stlv_offset+4));
1929                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+8, stlv_len - 4, "TNA Addr: %s",
1930                                         tvb_bytes_to_str(tvb, stlv_offset+8, stlv_len - 4));
1931                     break;
1932
1933                 default:
1934                     proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1935                                         "Unknown Link sub-TLV: %u", stlv_type);
1936                     break;
1937                 }
1938                 stlv_offset += ((stlv_len+4+3)/4)*4;
1939             }
1940             break;
1941         default:
1942             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
1943                                      "Unknown LSA: %u", tlv_type);
1944             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
1945             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: %u - Unknown",
1946                                 tlv_type);
1947             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
1948                                 tlv_length);
1949             proto_tree_add_text(tlv_tree, tvb, offset+4, tlv_length, "TLV Data");
1950             break;
1951         }
1952
1953         offset += tlv_length + 4;
1954         length -= tlv_length + 4;
1955     }
1956 }
1957
1958 /*
1959  * Dissect opaque LSAs
1960  */
1961 static void
1962 dissect_ospf_lsa_opaque(tvbuff_t *tvb, int offset, proto_tree *tree,
1963                         guint8 ls_id_type, guint32 length)
1964 {
1965     switch (ls_id_type) {
1966
1967     case OSPF_LSA_MPLS_TE:
1968         dissect_ospf_lsa_mpls(tvb, offset, tree, length);
1969         break;
1970
1971     default:
1972         proto_tree_add_text(tree, tvb, offset, length,
1973                             "Unknown LSA Type %u", ls_id_type);
1974         break;
1975     } /* switch on opaque LSA id */
1976 }
1977
1978 static int
1979 dissect_ospf_v2_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
1980                  gboolean disassemble_body)
1981 {
1982     proto_tree *ospf_lsa_tree;
1983     proto_item *ti;
1984
1985     guint8               ls_type;
1986     guint16              ls_length;
1987     int                  end_offset;
1988     guint16              nr_links;
1989     guint16              nr_tos;
1990
1991     /* router LSA */
1992     guint8               link_type;
1993     guint16              link_counter;
1994     guint8               tos_counter;
1995     const char          *link_type_str;
1996     const char          *link_type_short_str;
1997     const char          *link_id;
1998
1999     /* AS-external LSA */
2000     guint8               options;
2001
2002     /* opaque LSA */
2003     guint8               ls_id_type;
2004
2005     ls_type = tvb_get_guint8(tvb, offset + 3);
2006     ls_length = tvb_get_ntohs(tvb, offset + 18);
2007     end_offset = offset + ls_length;
2008
2009     if (disassemble_body) {
2010         ti = proto_tree_add_text(tree, tvb, offset, ls_length,
2011                                  "LS Type: %s",
2012                                  val_to_str(ls_type, ls_type_vals, "Unknown (%d)"));
2013     } else {
2014         ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
2015                                  "LSA Header");
2016     }
2017     ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
2018
2019     proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
2020                         tvb_get_ntohs(tvb, offset));
2021     dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset + 2, &bfinfo_v2_options);
2022     proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_LS_TYPE], tvb,
2023                         offset + 3, 1, FALSE);
2024     proto_tree_add_item_hidden(ospf_lsa_tree,
2025                                ospf_filter[ospf_ls_type_to_filter(ls_type)], tvb,
2026                                offset + 3, 1, FALSE);
2027
2028     if (is_opaque(ls_type)) {
2029         ls_id_type = tvb_get_guint8(tvb, offset + 4);
2030         proto_tree_add_uint(ospf_lsa_tree, ospf_filter[OSPFF_LS_OPAQUE_TYPE],
2031                             tvb, offset + 4, 1, ls_id_type);
2032
2033         switch (ls_id_type) {
2034
2035         case OSPF_LSA_MPLS_TE:
2036             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 1, "Link State ID TE-LSA Reserved: %u",
2037                                 tvb_get_guint8(tvb, offset + 5));
2038             proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_LS_MPLS_TE_INSTANCE],
2039                                 tvb, offset + 6, 2, FALSE);
2040             break;
2041
2042         default:
2043             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3, "Link State ID Opaque ID: %u",
2044                                 tvb_get_ntoh24(tvb, offset + 5));
2045             break;
2046         }
2047     } else {
2048         ls_id_type = 0;
2049         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
2050                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
2051     }
2052
2053     proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_ADV_ROUTER],
2054                         tvb, offset + 8, 4, FALSE);
2055     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%08x",
2056                         tvb_get_ntohl(tvb, offset + 12));
2057     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
2058                         tvb_get_ntohs(tvb, offset + 16));
2059
2060     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
2061                         ls_length);
2062
2063     /* skip past the LSA header to the body */
2064     offset += OSPF_LSA_HEADER_LENGTH;
2065     if (ls_length <= OSPF_LSA_HEADER_LENGTH)
2066         return offset;  /* no data, or bogus length */
2067     ls_length -= OSPF_LSA_HEADER_LENGTH;
2068
2069     if (!disassemble_body)
2070         return offset;
2071
2072     switch (ls_type){
2073
2074     case OSPF_LSTYPE_ROUTER:
2075         /* flags field in an router-lsa */
2076         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset, &bfinfo_v2_router_lsa_flags);
2077
2078         nr_links = tvb_get_ntohs(tvb, offset + 2);
2079         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "Number of Links: %u",
2080                             nr_links);
2081         offset += 4;
2082         /* nr_links links follow
2083          * maybe we should put each of the links into its own subtree ???
2084          */
2085         for (link_counter = 1; link_counter <= nr_links; link_counter++) {
2086             proto_tree *ospf_lsa_router_link_tree;
2087             proto_item *ti_local;
2088
2089
2090             /* check the Link Type and ID */
2091             link_type = tvb_get_guint8(tvb, offset + 8);
2092             switch (link_type) {
2093
2094             case OSPF_LINK_PTP:
2095                 link_type_str="Point-to-point connection to another router";
2096                 link_type_short_str="PTP";
2097                 link_id="Neighboring router's Router ID";
2098                 break;
2099
2100             case OSPF_LINK_TRANSIT:
2101                 link_type_str="Connection to a transit network";
2102                 link_type_short_str="Transit";
2103                 link_id="IP address of Designated Router";
2104                 break;
2105
2106             case OSPF_LINK_STUB:
2107                 link_type_str="Connection to a stub network";
2108                 link_type_short_str="Stub";
2109                 link_id="IP network/subnet number";
2110                 break;
2111
2112             case OSPF_LINK_VIRTUAL:
2113                 link_type_str="Virtual link";
2114                 link_type_short_str="Virtual";
2115                 link_id="Neighboring router's Router ID";
2116                 break;
2117
2118             default:
2119                 link_type_str="Unknown link type";
2120                 link_type_short_str="Unknown";
2121                 link_id="Unknown link ID";
2122                 break;
2123             }
2124
2125             nr_tos = tvb_get_guint8(tvb, offset + 9);
2126
2127             
2128             ti_local = proto_tree_add_text(ospf_lsa_tree, tvb, offset, 12 + 4 * nr_tos,
2129                                      "Type: %-8s ID: %-15s Data: %-15s Metric: %d",
2130                                      link_type_short_str, 
2131                                      ip_to_str(tvb_get_ptr(tvb, offset, 4)),
2132                                      ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)),
2133                                      tvb_get_ntohs(tvb, offset + 10));
2134
2135             ospf_lsa_router_link_tree = proto_item_add_subtree(ti_local, ett_ospf_lsa_router_link);
2136
2137             proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset, 4, "%s: %s", link_id,
2138                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2139
2140             /* link_data should be specified in detail (e.g. network mask) (depends on link type)*/
2141             proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 4, 4, "Link Data: %s",
2142                                 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
2143
2144             proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 8, 1, "Link Type: %u - %s",
2145                                 link_type, link_type_str);
2146             proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 9, 1, "Number of TOS metrics: %u",
2147                                 nr_tos);
2148             proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 10, 2, "TOS 0 metric: %u",
2149                                 tvb_get_ntohs(tvb, offset + 10));
2150
2151             offset += 12;
2152
2153             /* nr_tos metrics may follow each link
2154              * ATTENTION: TOS metrics are not tested (I don't have TOS
2155              * based routing)
2156              * please send me a mail if it is/isn't working
2157              */
2158             for (tos_counter = 1; tos_counter <= nr_tos; tos_counter++) {
2159                 proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
2160                                     tvb_get_guint8(tvb, offset),
2161                                     tvb_get_ntohs(tvb, offset + 2));
2162                 offset += 4;
2163             }
2164         }
2165         break;
2166
2167     case OSPF_LSTYPE_NETWORK:
2168         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
2169                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2170         offset += 4;
2171
2172         while (offset < end_offset) {
2173             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
2174                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2175             offset += 4;
2176         }
2177         break;
2178
2179     case OSPF_LSTYPE_SUMMERY:
2180     /* Type 3 and 4 LSAs have the same format */
2181     case OSPF_LSTYPE_ASBR:
2182         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
2183                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2184         offset += 4;
2185
2186         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Metric: %u",
2187                             tvb_get_ntoh24(tvb, offset + 1));
2188         offset += 4;
2189
2190         /* TOS-specific information, if any */
2191         while (offset < end_offset) {
2192             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
2193                                 tvb_get_guint8(tvb, offset),
2194                                 tvb_get_ntoh24(tvb, offset + 1));
2195             offset += 4;
2196         }
2197         break;
2198
2199     case OSPF_LSTYPE_ASEXT:
2200     case OSPF_LSTYPE_ASEXT7:
2201         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
2202                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2203         offset += 4;
2204
2205         options = tvb_get_guint8(tvb, offset);
2206         if (options & 0x80) { /* check wether or not E bit is set */
2207             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2208                     "External Type: Type 2 (metric is larger than any other link state path)");
2209         } else {
2210             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2211                     "External Type: Type 1 (metric is specified in the same units as interface cost)");
2212         }
2213         /* the metric field of a AS-external LAS is specified in 3 bytes */
2214         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3, "Metric: %u",
2215                             tvb_get_ntoh24(tvb, offset + 1));
2216         offset += 4;
2217
2218         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
2219                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2220         offset += 4;
2221
2222         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
2223                             tvb_get_ntohl(tvb, offset));
2224         offset += 4;
2225
2226         /* TOS-specific information, if any */
2227         while (offset < end_offset) {
2228             options = tvb_get_guint8(tvb, offset);
2229             if (options & 0x80) { /* check wether or not E bit is set */
2230                 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2231                         "External Type: Type 2 (metric is larger than any other link state path)");
2232             } else {
2233                 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2234                         "External Type: Type 1 (metric is specified in the same units as interface cost)");
2235             }
2236             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
2237                                 options & 0x7F,
2238                                 tvb_get_ntoh24(tvb, offset + 1));
2239             offset += 4;
2240
2241             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
2242                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2243             offset += 4;
2244
2245             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
2246                                 tvb_get_ntohl(tvb, offset));
2247             offset += 4;
2248         }
2249         break;
2250
2251     case OSPF_LSTYPE_OP_LINKLOCAL:
2252     case OSPF_LSTYPE_OP_AREALOCAL:
2253     case OSPF_LSTYPE_OP_ASWIDE:
2254         /*
2255          * RFC 2370 opaque LSAs.
2256          */
2257         dissect_ospf_lsa_opaque(tvb, offset, ospf_lsa_tree, ls_id_type,
2258                                 ls_length);
2259         offset += ls_length;
2260         break;
2261
2262     default:
2263         /* unknown LSA type */
2264         proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
2265                             "Unknown LSA Type");
2266         offset += ls_length;
2267         break;
2268     }
2269     /* return the offset of the next LSA */
2270     return offset;
2271 }
2272
2273 static int
2274 dissect_ospf_v3_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
2275                  gboolean disassemble_body)
2276 {
2277     proto_tree *ospf_lsa_tree;
2278     proto_item *ti;
2279
2280     guint16              ls_type;
2281     guint16              ls_length;
2282     int                  end_offset;
2283     guint8               reserved;
2284
2285     /* router LSA */
2286     guint8               link_type;
2287     const char          *link_type_str;
2288     guint32              metric;
2289
2290     guint8               router_priority;
2291     guint32              number_prefixes;
2292     guint8               prefix_length;
2293     guint16              reserved16;
2294
2295     guint16              referenced_ls_type;
2296
2297     guint8               flags;
2298     guint32              external_route_tag;
2299
2300
2301     ls_type = tvb_get_ntohs(tvb, offset + 2);
2302     ls_length = tvb_get_ntohs(tvb, offset + 18);
2303     end_offset = offset + ls_length;
2304
2305     if (disassemble_body) {
2306         ti = proto_tree_add_text(tree, tvb, offset, ls_length,
2307                                  "%s (Type: 0x%04x)", val_to_str(ls_type, v3_ls_type_vals,"Unknown"), ls_type);
2308     } else {
2309         ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
2310                                  "LSA Header");
2311     }
2312     ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
2313
2314     proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
2315                         tvb_get_ntohs(tvb, offset));
2316
2317     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "LSA Type: 0x%04x (%s)",
2318                         ls_type, val_to_str(ls_type, v3_ls_type_vals,"Unkown"));
2319
2320     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
2321                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
2322
2323     proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_ADV_ROUTER],
2324                         tvb, offset + 8, 4, FALSE);
2325     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%08x",
2326                         tvb_get_ntohl(tvb, offset + 12));
2327     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
2328                         tvb_get_ntohs(tvb, offset + 16));
2329
2330     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
2331                         ls_length);
2332
2333     /* skip past the LSA header to the body */
2334     offset += OSPF_LSA_HEADER_LENGTH;
2335     ls_length -= OSPF_LSA_HEADER_LENGTH;
2336
2337     if (!disassemble_body)
2338         return offset;
2339
2340     switch (ls_type){
2341
2342
2343     case OSPF_V3_LSTYPE_ROUTER:
2344         /* flags field in an router-lsa */
2345         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset, &bfinfo_v3_router_lsa_flags);
2346
2347         /* options field in an router-lsa */
2348         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset + 1, &bfinfo_v3_options);
2349
2350         /* skip the router-lsa flags and options */
2351         offset+=4;
2352         ls_length-=4;
2353
2354         if (ls_length > 0)
2355              proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
2356                    "Router Interfaces:");
2357
2358         /* scan all router-lsa router interfaces */
2359         /* maybe we should put each of the links into its own subtree ??? */
2360         while (ls_length > 0 ) {
2361
2362             /* check the type */
2363             link_type = tvb_get_guint8(tvb, offset);
2364             switch (link_type) {
2365
2366                 case OSPF_V3_LINK_PTP:
2367                     link_type_str="Point-to-point connection to another router";
2368                     break;
2369
2370                 case OSPF_V3_LINK_TRANSIT:
2371                     link_type_str="Connection to a transit network";
2372                     break;
2373
2374                 case OSPF_V3_LINK_RESERVED:
2375                     link_type_str="Connection to a stub network";
2376                     break;
2377
2378                 case OSPF_V3_LINK_VIRTUAL:
2379                     link_type_str="Virtual link";
2380                     break;
2381
2382                 default:
2383                     link_type_str="Unknown link type";
2384                     break;
2385             }
2386
2387             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Type: %u (%s)", link_type,link_type_str);
2388
2389             /* reserved field */
2390             reserved = tvb_get_guint8(tvb, offset+1);
2391             proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 1,
2392                (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved);
2393
2394             /* metric */
2395             metric=tvb_get_ntohs(tvb, offset+2);
2396             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2,"Metric: %u",metric);
2397
2398             /* Interface ID */
2399             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Interface ID: %u",
2400                         tvb_get_ntohl(tvb, offset + 4));
2401
2402             /* Neighbor Interface ID */
2403             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Neighbor Interface ID: %u",
2404                         tvb_get_ntohl(tvb, offset + 8));
2405
2406             /* Neighbor Router ID */
2407             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "Neighbor Router ID: %s",
2408                 ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
2409
2410             /* skip to the (possible) next entry */
2411             offset+=16;
2412             ls_length-=16;
2413
2414         }
2415         break;
2416
2417     case OSPF_V3_LSTYPE_NETWORK:
2418
2419         /* reserved field */
2420         reserved = tvb_get_guint8(tvb, offset);
2421         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2422                (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved);
2423
2424         /* options field in an network-lsa */
2425         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset + 1, &bfinfo_v3_options);
2426
2427         offset += 4;
2428         ls_length-=4;
2429
2430         while (ls_length > 0 ) {
2431             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
2432                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2433             ls_length-=4;
2434             offset += 4;
2435         }
2436         break;
2437
2438
2439     case OSPF_V3_LSTYPE_INTER_AREA_PREFIX:
2440
2441         /* reserved field */
2442         reserved = tvb_get_guint8(tvb, offset);
2443         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2444                (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved);
2445
2446         /* metric */
2447         metric=tvb_get_ntoh24(tvb, offset+1);
2448         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3,"Metric: %u",metric);
2449
2450         /* prefix length */
2451         prefix_length=tvb_get_guint8(tvb, offset+4);
2452         proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length);
2453
2454         /* prefix options */
2455         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset+5, &bfinfo_v3_prefix_options);
2456
2457         /* 16 bits reserved */
2458         reserved16=tvb_get_ntohs(tvb, offset+6);
2459         proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,
2460                (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved16);
2461
2462         offset+=8;
2463
2464         /* address_prefix */
2465         dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
2466
2467         offset+=(prefix_length+31)/32*4;
2468
2469         break;
2470
2471
2472     case OSPF_V3_LSTYPE_INTER_AREA_ROUTER:
2473
2474         /* reserved field */
2475         reserved = tvb_get_guint8(tvb, offset);
2476         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2477                (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved);
2478
2479         /* options field in an inter-area-router-lsa */
2480         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset + 1, &bfinfo_v3_options);
2481
2482         /* reserved field */
2483         reserved = tvb_get_guint8(tvb, offset+4);
2484         proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1,
2485                (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved);
2486
2487         /* metric */
2488         metric=tvb_get_ntoh24(tvb, offset+5);
2489         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3,"Metric: %u",metric);
2490
2491         /* Destination Router ID */
2492         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Destination Router ID: %s",
2493                 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
2494
2495         offset+=12;
2496         break;
2497
2498
2499     case OSPF_V3_LSTYPE_TYPE_7:
2500     case OSPF_V3_LSTYPE_AS_EXTERNAL:
2501
2502         /* flags */
2503         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset, &bfinfo_v3_as_external_flags);
2504         flags=tvb_get_guint8(tvb, offset);
2505
2506         /* 24 bits metric */
2507         metric=tvb_get_ntoh24(tvb, offset+1);
2508         proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 3,
2509                                 "Metric: %u", metric);
2510
2511         /* prefix length */
2512         prefix_length=tvb_get_guint8(tvb, offset+4);
2513         proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length);
2514
2515         /* prefix options */
2516         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset+5, &bfinfo_v3_prefix_options);
2517
2518         /* referenced LS type */
2519         referenced_ls_type=tvb_get_ntohs(tvb, offset+6);
2520         proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,"Referenced LS type 0x%04x (%s)",
2521                             referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
2522
2523         offset+=8;
2524
2525         /* address_prefix */
2526         dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
2527
2528         offset+=(prefix_length+31)/32*4;
2529
2530         /* Forwarding Address (optional - only if F-flag is on) */
2531         if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_F) ) {
2532             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 16,"Forwarding Address: %s",
2533               ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16)));
2534
2535             offset+=16;
2536         }
2537
2538         /* External Route Tag (optional - only if T-flag is on) */
2539         if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_T) ) {
2540             external_route_tag=tvb_get_ntohl(tvb, offset);
2541             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4,"External Route Tag: %u",
2542                                 external_route_tag);
2543
2544             offset+=4;
2545         }
2546
2547         /* Referenced Link State ID (optional - only if Referenced LS type is non-zero */
2548         if ( (offset < end_offset) && (referenced_ls_type != 0) ) {
2549             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Referenced Link State ID: %s",
2550                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2551             offset+=4;
2552         }
2553
2554         break;
2555
2556     case OSPF_V3_LSTYPE_LINK:
2557
2558         /* router priority */
2559         router_priority=tvb_get_guint8(tvb, offset);
2560         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Router Priority: %u", router_priority);
2561
2562         /* options field in an link-lsa */
2563         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset + 1, &bfinfo_v3_options);
2564
2565         /* Link-local Interface Address */
2566         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 16, "Link-local Interface Address: %s",
2567            ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 4, 16)));
2568
2569         /* Number prefixes */
2570         number_prefixes=tvb_get_ntohl(tvb, offset + 20);
2571         proto_tree_add_text(ospf_lsa_tree, tvb, offset+20, 4, "# prefixes: %d",number_prefixes);
2572
2573         offset+=24;
2574
2575         while (number_prefixes > 0) {
2576
2577             /* prefix length */
2578             prefix_length=tvb_get_guint8(tvb, offset);
2579             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length);
2580
2581             /* prefix options */
2582             dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset+1, &bfinfo_v3_prefix_options);
2583
2584             /* 16 bits reserved */
2585             reserved16=tvb_get_ntohs(tvb, offset+2);
2586             proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,
2587                (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved16);
2588
2589             offset+=4;
2590
2591             /* address_prefix */
2592             dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
2593
2594             offset+=(prefix_length+31)/32*4;
2595
2596             number_prefixes--;
2597
2598         }
2599         break;
2600
2601     case OSPF_V3_LSTYPE_INTRA_AREA_PREFIX:
2602
2603         /* # prefixes */
2604         number_prefixes=tvb_get_ntohs(tvb, offset);
2605         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2,"# prefixes: %u",number_prefixes);
2606
2607         /* referenced LS type */
2608         referenced_ls_type=tvb_get_ntohs(tvb, offset+2);
2609         proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,"Referenced LS type 0x%04x (%s)",
2610                             referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
2611
2612         /* Referenced Link State ID */
2613         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Referenced Link State ID: %s",
2614                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
2615
2616         /* Referenced Advertising Router */
2617         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Referenced Advertising Router: %s",
2618                             ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
2619
2620         offset+=12;
2621
2622         while (number_prefixes > 0) {
2623
2624             /* prefix length */
2625             prefix_length=tvb_get_guint8(tvb, offset);
2626             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length);
2627
2628             /* prefix options */
2629             dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset+1, &bfinfo_v3_prefix_options);
2630
2631             /* 16 bits metric */
2632             metric=tvb_get_ntohs(tvb, offset+2);
2633             proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,
2634                                 "Metric: %u", metric);
2635
2636             offset+=4;
2637
2638             /* address_prefix */
2639             dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
2640
2641             offset+=(prefix_length+31)/32*4;
2642
2643             number_prefixes--;
2644         }
2645         break;
2646
2647     default:
2648         /* unknown LSA type */
2649         proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
2650                             "Unknown LSA Type 0x%04x",ls_type);
2651         offset += ls_length;
2652         break;
2653     }
2654     /* return the offset of the next LSA */
2655     return offset;
2656 }
2657
2658 static void dissect_ospf_v3_address_prefix(tvbuff_t *tvb, int offset, int prefix_length, proto_tree *tree)
2659 {
2660
2661     int bytes_to_process;
2662     struct e_in6_addr prefix;
2663
2664     bytes_to_process=((prefix_length+31)/32)*4;
2665
2666     if (prefix_length > 128) {
2667         proto_tree_add_text(tree, tvb, offset, bytes_to_process,
2668             "Address Prefix: length is invalid (%d, should be <= 128)",
2669             prefix_length);
2670         return;
2671     }
2672
2673     memset(prefix.bytes, 0, sizeof prefix.bytes);
2674     if (bytes_to_process != 0) {
2675         tvb_memcpy(tvb, prefix.bytes, offset, bytes_to_process);
2676         if (prefix_length % 8) {
2677             prefix.bytes[bytes_to_process - 1] &=
2678                 ((0xff00 >> (prefix_length % 8)) & 0xff);
2679         }
2680     }
2681     proto_tree_add_text(tree, tvb, offset, bytes_to_process,
2682         "Address Prefix: %s", ip6_to_str(&prefix));
2683
2684 }
2685
2686
2687 void
2688 proto_register_ospf(void)
2689 {
2690     static gint *ett[] = {
2691         &ett_ospf,
2692         &ett_ospf_hdr,
2693         &ett_ospf_hello,
2694         &ett_ospf_desc,
2695         &ett_ospf_lsr,
2696         &ett_ospf_lsa,
2697         &ett_ospf_lsa_router_link,
2698         &ett_ospf_lsa_upd,
2699         &ett_ospf_lsa_mpls,
2700         &ett_ospf_lsa_mpls_router,
2701         &ett_ospf_lsa_mpls_link,
2702         &ett_ospf_lsa_mpls_link_stlv,
2703         &ett_ospf_lsa_mpls_link_stlv_admingrp,
2704         &ett_ospf_lsa_oif_tna,
2705         &ett_ospf_lsa_oif_tna_stlv,
2706         &ett_ospf_v2_options,
2707         &ett_ospf_v3_options,
2708         &ett_ospf_dbd,
2709         &ett_ospf_lls_data_block,
2710         &ett_ospf_lls_tlv,
2711         &ett_ospf_lls_ext_options,
2712         &ett_ospf_v2_router_lsa_flags,
2713         &ett_ospf_v3_router_lsa_flags,
2714         &ett_ospf_v3_as_external_flags,
2715         &ett_ospf_v3_prefix_options
2716     };
2717
2718     proto_ospf = proto_register_protocol("Open Shortest Path First",
2719                                          "OSPF", "ospf");
2720     proto_register_field_array(proto_ospf, ospff_info, array_length(ospff_info));
2721     proto_register_subtree_array(ett, array_length(ett));
2722 }
2723
2724 void
2725 proto_reg_handoff_ospf(void)
2726 {
2727     dissector_handle_t ospf_handle;
2728
2729     ospf_handle = create_dissector_handle(dissect_ospf, proto_ospf);
2730     dissector_add("ip.proto", IP_PROTO_OSPF, ospf_handle);
2731     data_handle = find_dissector("data");
2732 }