f11bff263e4d5e29bb274e7c5066bc42546fe062
[obnox/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  * Wireshark - Network traffic analyzer
26  * By Gerald Combs <gerald@wireshark.org>
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     size_t length, pos;
827     gint i;
828     header_field_info *hfinfo;
829     int hfindex, index;
830     size_t returned_length;
831
832     hfindex = ospf_filter[bfinfo->hfindex];
833     hfinfo = proto_registrar_get_nth(hfindex);
834     switch (hfinfo->type) {
835         case FT_UINT8:
836             flags = tvb_get_guint8(tvb, offset);
837             length = 1;
838             break;
839         case FT_UINT16:
840             flags = tvb_get_ntohs(tvb, offset);
841             length = 2;
842             break;
843         case FT_UINT24:
844             flags = tvb_get_ntoh24(tvb, offset);
845             length = 3;
846             break;
847         case FT_UINT32:
848             flags = tvb_get_ntohl(tvb, offset);
849             length = 4;
850             break;
851         default:
852             return;
853     }
854
855     if (parent_tree) {
856         item = proto_tree_add_uint(parent_tree, hfindex, tvb, offset, length, flags);
857         tree = proto_item_add_subtree(item, *bfinfo->ett);
858
859         str = ep_alloc(MAX_OPTIONS_LEN);
860         str[0] = 0;
861         for (i = 0, pos = 0; i < bfinfo->num; i++) {
862             index = ospf_filter[bfinfo->index[i]];
863             hfinfo = proto_registrar_get_nth(index);
864             if (flags & hfinfo->bitmask) {
865                 returned_length = g_snprintf(&str[pos], MAX_OPTIONS_LEN-pos, "%s%s",
866                                   pos ? ", " : "",
867                                   hfinfo->name);
868                 pos += MIN(returned_length, MAX_OPTIONS_LEN-pos);
869             }
870             proto_tree_add_boolean(tree, index, tvb, offset, length, flags);
871         }
872         proto_item_append_text(item, " (%s)", str);
873     }
874 }
875
876 static dissector_handle_t data_handle;
877
878 static void dissect_ospf_hello(tvbuff_t*, int, proto_tree*, guint8, guint16);
879 static void dissect_ospf_db_desc(tvbuff_t*, int, proto_tree*, guint8, guint16);
880 static void dissect_ospf_ls_req(tvbuff_t*, int, proto_tree*, guint8, guint16);
881 static void dissect_ospf_ls_upd(tvbuff_t*, int, proto_tree*, guint8, guint16);
882 static void dissect_ospf_ls_ack(tvbuff_t*, int, proto_tree*, guint8, guint16);
883 static void dissect_ospf_lls_data_block(tvbuff_t*, int, proto_tree*, guint8);
884
885 /* dissect_ospf_v[23]lsa returns the offset of the next LSA
886  * if disassemble_body is set to FALSE (e.g. in LSA ACK
887  * packets), the offset is set to the offset of the next
888  * LSA header
889  */
890 static int dissect_ospf_v2_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body);
891 static int dissect_ospf_v3_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body);
892
893 static void dissect_ospf_v3_address_prefix(tvbuff_t *, int, int, proto_tree *);
894
895 static int 
896 ospf_has_lls_block(tvbuff_t *tvb, int offset, guint8 packet_type)
897 {
898     guint8 flags;
899
900     /* LLS block can be found only in HELLO and DBDESC packets */
901     switch (packet_type) {
902     case OSPF_HELLO:
903         flags = tvb_get_guint8 (tvb, offset + 6);
904         return flags & OSPF_V2_OPTIONS_L;
905     case OSPF_DB_DESC:
906         flags = tvb_get_guint8 (tvb, offset + 2);
907         return flags & OSPF_V2_OPTIONS_L;
908     }
909
910     return 0;
911 }
912
913 static void
914 dissect_ospf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
915 {
916     proto_tree *ospf_tree = NULL;
917     proto_item *ti;
918     proto_tree *ospf_header_tree;
919     guint8  version;
920     guint8  packet_type;
921     guint16 ospflen;
922     vec_t cksum_vec[4];
923     int cksum_vec_len;
924     guint32 phdr[2];
925     guint16 cksum, computed_cksum;
926     guint length, reported_length;
927     guint16 auth_type;
928     char auth_data[8+1];
929     int crypto_len = 0;
930     unsigned int ospf_header_length;
931     guint8 instance_ID;
932     guint8 reserved;
933     guint32 areaid;
934
935
936     if (check_col(pinfo->cinfo, COL_PROTOCOL))
937         col_set_str(pinfo->cinfo, COL_PROTOCOL, "OSPF");
938     if (check_col(pinfo->cinfo, COL_INFO))
939         col_clear(pinfo->cinfo, COL_INFO);
940
941     version = tvb_get_guint8(tvb, 0);
942     switch (version) {
943         case OSPF_VERSION_2:
944             ospf_header_length = OSPF_VERSION_2_HEADER_LENGTH;
945             break;
946         case OSPF_VERSION_3:
947             ospf_header_length = OSPF_VERSION_3_HEADER_LENGTH;
948             break;
949         default:
950             ospf_header_length = 14;
951             break;
952     }
953
954     packet_type = tvb_get_guint8(tvb, 1);
955     if (check_col(pinfo->cinfo, COL_INFO)) {
956         col_add_str(pinfo->cinfo, COL_INFO,
957                     val_to_str(packet_type, pt_vals, "Unknown (%u)"));
958     }
959
960     if (tree) {
961         ospflen = tvb_get_ntohs(tvb, 2);
962
963         ti = proto_tree_add_item(tree, proto_ospf, tvb, 0, -1, FALSE);
964         ospf_tree = proto_item_add_subtree(ti, ett_ospf);
965
966         ti = proto_tree_add_text(ospf_tree, tvb, 0, ospf_header_length,
967                                  "OSPF Header");
968         ospf_header_tree = proto_item_add_subtree(ti, ett_ospf_hdr);
969
970         proto_tree_add_text(ospf_header_tree, tvb, 0, 1, "OSPF Version: %u",
971                             version);
972         proto_tree_add_item(ospf_header_tree, ospf_filter[OSPFF_MSG_TYPE],
973                             tvb, 1, 1, FALSE);
974         proto_tree_add_item_hidden(ospf_header_tree,
975                                    ospf_filter[ospf_msg_type_to_filter(packet_type)],
976                                    tvb, 1, 1, FALSE);
977         proto_tree_add_text(ospf_header_tree, tvb, 2, 2, "Packet Length: %u",
978                             ospflen);
979         proto_tree_add_item(ospf_header_tree, ospf_filter[OSPFF_SRC_ROUTER],
980                             tvb, 4, 4, FALSE);
981         areaid=tvb_get_ntohl(tvb,8);
982         proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: %s%s",
983                                ip_to_str(tvb_get_ptr(tvb, 8, 4)), areaid == 0 ? " (Backbone)" : "");
984
985         /*
986          * Quit at this point if it's an unknown OSPF version.
987          */
988         switch (version) {
989
990         case OSPF_VERSION_2:
991         case OSPF_VERSION_3:
992             break;
993
994         default:
995             cksum = tvb_get_ntohs(tvb, 12);
996             if (cksum == 0) {
997                 /* No checksum supplied in the packet. */
998                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
999                     "Packet Checksum: 0x%04x (none)", cksum);
1000             } else {
1001                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
1002                     "Packet Checksum: 0x%04x", cksum);
1003             }
1004             proto_tree_add_text(ospf_tree, tvb, 14, -1,
1005                 "Unknown OSPF version %u", version);
1006             return;
1007         }
1008
1009         cksum = tvb_get_ntohs(tvb, 12);
1010         length = tvb_length(tvb);
1011         /* XXX - include only the length from the OSPF header? */
1012         reported_length = tvb_reported_length(tvb);
1013         if (cksum == 0) {
1014             /* No checksum supplied in the packet. */
1015             proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
1016                 "Packet Checksum: 0x%04x (none)", cksum);
1017         } else if (!pinfo->fragmented && length >= reported_length
1018                 && length >= ospf_header_length) {
1019             /* The packet isn't part of a fragmented datagram and isn't
1020                truncated, so we can checksum it. */
1021
1022             switch (version) {
1023
1024             case OSPF_VERSION_2:
1025                 /* Header, not including the authentication data (the OSPFv2
1026                    checksum excludes the 64-bit authentication field). */
1027                 cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, 16);
1028                 cksum_vec[0].len = 16;
1029                 if (length > ospf_header_length) {
1030                     /* Rest of the packet, again not including the
1031                        authentication data. */
1032                     reported_length -= ospf_header_length;
1033                     cksum_vec[1].ptr = tvb_get_ptr(tvb, ospf_header_length, reported_length);
1034                     cksum_vec[1].len = reported_length;
1035                     cksum_vec_len = 2;
1036                 } else {
1037                     /* There's nothing but a header. */
1038                     cksum_vec_len = 1;
1039                 }
1040                 break;
1041
1042             case OSPF_VERSION_3:
1043                 /* IPv6-style checksum, covering the entire OSPF packet
1044                    and a prepended IPv6 pseudo-header. */
1045
1046                 /* Set up the fields of the pseudo-header. */
1047                 cksum_vec[0].ptr = pinfo->src.data;
1048                 cksum_vec[0].len = pinfo->src.len;
1049                 cksum_vec[1].ptr = pinfo->dst.data;
1050                 cksum_vec[1].len = pinfo->dst.len;
1051                 cksum_vec[2].ptr = (const guint8 *)&phdr;
1052                 phdr[0] = g_htonl(ospflen);
1053                 phdr[1] = g_htonl(IP_PROTO_OSPF);
1054                 cksum_vec[2].len = 8;
1055
1056                 cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, reported_length);
1057                 cksum_vec[3].len = reported_length;
1058                 cksum_vec_len = 4;
1059                 break;
1060
1061             default:
1062                 DISSECTOR_ASSERT_NOT_REACHED();
1063                 cksum_vec_len = 0;
1064                 break;
1065             }
1066             computed_cksum = in_cksum(cksum_vec, cksum_vec_len);
1067             if (computed_cksum == 0) {
1068                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
1069                         "Packet Checksum: 0x%04x [correct]", cksum);
1070             } else {
1071                 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
1072                         "Packet Checksum: 0x%04x [incorrect, should be 0x%04x]",
1073                         cksum, in_cksum_shouldbe(cksum, computed_cksum));
1074             }
1075         } else {
1076             proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
1077                 "Packet Checksum: 0x%04x", cksum);
1078         }
1079
1080
1081         switch (version) {
1082
1083         case OSPF_VERSION_2:
1084             /* Authentication is only valid for OSPFv2 */
1085             auth_type = tvb_get_ntohs(tvb, 14);
1086             proto_tree_add_text(ospf_header_tree, tvb, 14, 2, "Auth Type: %s",
1087                             val_to_str(auth_type, auth_vals, "Unknown (%u)"));
1088             switch (auth_type) {
1089
1090             case OSPF_AUTH_NONE:
1091                 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (none)");
1092                 break;
1093
1094             case OSPF_AUTH_SIMPLE:
1095                 tvb_get_nstringz0(tvb, 16, 8+1, auth_data);
1096                 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data: %s", auth_data);
1097                 break;
1098
1099             case OSPF_AUTH_CRYPT:
1100                 proto_tree_add_text(ospf_header_tree, tvb, 18, 1, "Auth Key ID: %u",
1101                                 tvb_get_guint8(tvb, 18));
1102                 crypto_len = tvb_get_guint8(tvb, 19);
1103                 proto_tree_add_text(ospf_header_tree, tvb, 19, 1, "Auth Data Length: %u",
1104                                 crypto_len);
1105                 proto_tree_add_text(ospf_header_tree, tvb, 20, 4, "Auth Crypto Sequence Number: 0x%x",
1106                                 tvb_get_ntohl(tvb, 20));
1107
1108                 /* Show the message digest that was appended to the end of the
1109                    OSPF message - but only if it's present (we don't want
1110                    to get an exception before we've tried dissecting OSPF
1111                    message). */
1112                 if (tvb_bytes_exist(tvb, ospflen, crypto_len)) {
1113                     proto_tree_add_text(ospf_header_tree, tvb, ospflen, crypto_len,
1114                                     "Auth Data: %s",
1115                                     tvb_bytes_to_str(tvb, ospflen, crypto_len));
1116                 }
1117                 break;
1118
1119             default:
1120                 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (unknown)");
1121                 break;
1122             }
1123             break;
1124
1125         case OSPF_VERSION_3:
1126             /* Instance ID and "reserved" is OSPFv3-only */
1127             instance_ID = tvb_get_guint8(tvb, 14);
1128             proto_tree_add_text(ospf_header_tree, tvb, 14, 1, "Instance ID: %u",
1129                             instance_ID);
1130             reserved = tvb_get_guint8(tvb, 15);
1131             proto_tree_add_text(ospf_header_tree, tvb, 15, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),
1132                                 reserved);
1133             break;
1134         }
1135
1136         switch (packet_type){
1137
1138         case OSPF_HELLO:
1139             dissect_ospf_hello(tvb, ospf_header_length, ospf_tree, version, 
1140                             ospflen - ospf_header_length);
1141             break;
1142
1143         case OSPF_DB_DESC:
1144             dissect_ospf_db_desc(tvb, ospf_header_length, ospf_tree, version, 
1145                             ospflen - ospf_header_length);
1146             break;
1147
1148         case OSPF_LS_REQ:
1149             dissect_ospf_ls_req(tvb, ospf_header_length, ospf_tree, version, 
1150                             ospflen - ospf_header_length);
1151             break;
1152
1153         case OSPF_LS_UPD:
1154             dissect_ospf_ls_upd(tvb, ospf_header_length, ospf_tree, version, 
1155                             ospflen - ospf_header_length);
1156             break;
1157
1158         case OSPF_LS_ACK:
1159             dissect_ospf_ls_ack(tvb, ospf_header_length, ospf_tree, version, 
1160                             ospflen - ospf_header_length);
1161             break;
1162
1163         default:
1164             call_dissector(data_handle,
1165                 tvb_new_subset(tvb, ospf_header_length, -1, -1), pinfo, tree);
1166             break;
1167         }
1168
1169         /* take care of the LLS data block */
1170         if (ospf_has_lls_block(tvb, ospf_header_length, packet_type))
1171             dissect_ospf_lls_data_block(tvb, ospflen + crypto_len, ospf_tree, 
1172                             version);
1173     }
1174 }
1175
1176 static int
1177 dissect_ospf_lls_tlv(tvbuff_t *tvb, int offset, proto_tree *tree)
1178 {
1179     proto_item *ti;
1180     proto_tree *ospf_lls_tlv_tree;
1181     guint16 type;
1182     guint16 length;
1183
1184     type = tvb_get_ntohs(tvb, offset);
1185     length = tvb_get_ntohs(tvb, offset + 2);
1186
1187     ti = proto_tree_add_text(tree, tvb, offset, length + 4, 
1188                     val_to_str(type, lls_tlv_type_vals, "Unknown TLV"));
1189     ospf_lls_tlv_tree = proto_item_add_subtree(ti, ett_ospf_lls_tlv);
1190     
1191     proto_tree_add_text(ospf_lls_tlv_tree, tvb, offset, 2,
1192                     "Type: %d", type);
1193     proto_tree_add_text(ospf_lls_tlv_tree, tvb, offset + 2, 2,
1194                     "Length: %d", length);
1195       
1196     switch(type) {
1197         case 1:
1198             dissect_ospf_bitfield(ospf_lls_tlv_tree, tvb, offset + 4, &bfinfo_lls_ext_options);
1199             break;
1200         case 2:
1201             proto_tree_add_text(ospf_lls_tlv_tree, tvb, offset + 4, 4, 
1202                             "Sequence number 0x%08x", 
1203                             tvb_get_ntohl(tvb, offset + 4));
1204             proto_tree_add_text(ospf_lls_tlv_tree, tvb, offset + 8, length - 4,
1205                             "Auth Data: %s", 
1206                             tvb_bytes_to_str(tvb, offset + 8, length - 4));
1207             break;
1208     }
1209
1210     return offset + length + 4;
1211 }
1212
1213 static void
1214 dissect_ospf_lls_data_block(tvbuff_t *tvb, int offset, proto_tree *tree, 
1215                 guint8 version)
1216 {
1217     proto_tree *ospf_lls_data_block_tree;
1218     proto_item *ti;
1219     guint16 ospf_lls_len;
1220     int orig_offset = offset;
1221
1222     ospf_lls_len = tvb_get_ntohs(tvb, offset + 2);
1223     ti = proto_tree_add_text(tree, tvb, offset, -1, "OSPF LLS Data Block");
1224     ospf_lls_data_block_tree = proto_item_add_subtree(ti, 
1225                     ett_ospf_lls_data_block);
1226
1227     if (version != OSPF_VERSION_2)
1228             return;
1229
1230     /* TODO: verify checksum */
1231     proto_tree_add_text(ospf_lls_data_block_tree, tvb, offset, 2, 
1232                     "Checksum: 0x%04x", tvb_get_ntohs(tvb, offset));
1233     proto_tree_add_text(ospf_lls_data_block_tree, tvb, offset + 2, 2,
1234                     "LLS Data Length: %d bytes", ospf_lls_len * 4);
1235     
1236     offset += 4;
1237     while (orig_offset + ospf_lls_len * 4 > offset)
1238         offset = dissect_ospf_lls_tlv (tvb, offset, ospf_lls_data_block_tree);
1239 }
1240
1241 static void
1242 dissect_ospf_hello(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version, 
1243                 guint16 length)
1244 {
1245     proto_tree *ospf_hello_tree;
1246     proto_item *ti;
1247     int orig_offset = offset;
1248
1249     ti = proto_tree_add_text(tree, tvb, offset, length, "OSPF Hello Packet");
1250     ospf_hello_tree = proto_item_add_subtree(ti, ett_ospf_hello);
1251
1252     switch (version ) {
1253         case OSPF_VERSION_2:
1254             proto_tree_add_text(ospf_hello_tree, tvb, offset, 4, "Network Mask: %s",
1255                         ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1256             proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 2,
1257                         "Hello Interval: %u seconds",
1258                         tvb_get_ntohs(tvb, offset + 4));
1259
1260             dissect_ospf_bitfield(ospf_hello_tree, tvb, offset + 6, &bfinfo_v2_options);
1261             proto_tree_add_text(ospf_hello_tree, tvb, offset + 7, 1, "Router Priority: %u",
1262                         tvb_get_guint8(tvb, offset + 7));
1263             proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 4, "Router Dead Interval: %u seconds",
1264                         tvb_get_ntohl(tvb, offset + 8));
1265             proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
1266                         ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
1267             proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
1268                         ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
1269
1270             offset += 20;
1271             while (orig_offset + length > offset) {
1272                 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
1273                             "Active Neighbor: %s",
1274                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1275                 offset += 4;
1276             }
1277             break;
1278         case OSPF_VERSION_3:
1279             proto_tree_add_text(ospf_hello_tree, tvb, offset + 0, 4, "Interface ID: %u",
1280                         tvb_get_ntohl(tvb, offset + 0));
1281             proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 1, "Router Priority: %u",
1282                         tvb_get_guint8(tvb, offset + 4));
1283             dissect_ospf_bitfield(ospf_hello_tree, tvb, offset + 5, &bfinfo_v3_options);
1284             proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 2,
1285                         "Hello Interval: %u seconds",
1286                         tvb_get_ntohs(tvb, offset + 8));
1287             proto_tree_add_text(ospf_hello_tree, tvb, offset + 10, 2, "Router Dead Interval: %u seconds",
1288                         tvb_get_ntohs(tvb, offset + 10));
1289             proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
1290                         ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
1291             proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
1292                         ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
1293             offset += 20;
1294             while (orig_offset + length > offset) {
1295                 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
1296                             "Active Neighbor: %s",
1297                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1298                 offset += 4;
1299             }
1300
1301             break;
1302     }
1303 }
1304
1305 static void
1306 dissect_ospf_db_desc(tvbuff_t *tvb, int offset, proto_tree *tree, 
1307                 guint8 version, guint16 length)
1308 {
1309     proto_tree *ospf_db_desc_tree=NULL;
1310     proto_item *ti;
1311     guint8 reserved;
1312     int orig_offset = offset;
1313
1314     if (tree) {
1315         ti = proto_tree_add_text(tree, tvb, offset, length, "OSPF DB Description");
1316         ospf_db_desc_tree = proto_item_add_subtree(ti, ett_ospf_desc);
1317
1318         switch (version ) {
1319
1320             case OSPF_VERSION_2:
1321                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 2, "Interface MTU: %u",
1322                             tvb_get_ntohs(tvb, offset));
1323
1324                 dissect_ospf_bitfield(ospf_db_desc_tree, tvb, offset + 2, &bfinfo_v2_options);
1325                 dissect_ospf_bitfield(ospf_db_desc_tree, tvb, offset + 3, &bfinfo_dbd);
1326
1327                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 4, "DD Sequence: %u",
1328                             tvb_get_ntohl(tvb, offset + 4));
1329
1330                 offset += 8;
1331                 break;
1332
1333             case OSPF_VERSION_3:
1334
1335                 reserved = tvb_get_guint8(tvb, offset);
1336                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),
1337                                 reserved);
1338
1339                 dissect_ospf_bitfield(ospf_db_desc_tree, tvb, offset + 1, &bfinfo_v3_options);
1340
1341                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 2, "Interface MTU: %u",
1342                             tvb_get_ntohs(tvb, offset+4));
1343
1344                 reserved = tvb_get_guint8(tvb, offset + 6);
1345                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 6, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),
1346                                 reserved);
1347
1348                 dissect_ospf_bitfield(ospf_db_desc_tree, tvb, offset + 7, &bfinfo_dbd);
1349
1350                 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 8, 4, "DD Sequence: %u",
1351                             tvb_get_ntohl(tvb, offset + 8));
1352
1353                 offset += 12;
1354                 break;
1355         }
1356     }
1357
1358     /* LS Headers will be processed here */
1359     /* skip to the end of DB-Desc header */
1360     while (orig_offset + length > offset) {
1361       if ( version == OSPF_VERSION_2)
1362           offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE);
1363       else
1364           if ( version == OSPF_VERSION_3)
1365               offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE);
1366     }
1367
1368 }
1369
1370 static void
1371 dissect_ospf_ls_req(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version,
1372                 guint16 length)
1373 {
1374     proto_tree *ospf_lsr_tree;
1375     proto_item *ti;
1376     guint32 ls_type;
1377     guint16 reserved;
1378     int orig_offset = offset;
1379
1380     /* zero or more LS requests may be within a LS Request */
1381     /* we place every request for a LSA in a single subtree */
1382     while (orig_offset + length > offset) {
1383         ti = proto_tree_add_text(tree, tvb, offset, OSPF_LS_REQ_LENGTH,
1384                                  "Link State Request");
1385         ospf_lsr_tree = proto_item_add_subtree(ti, ett_ospf_lsr);
1386
1387         switch ( version ) {
1388
1389             case OSPF_VERSION_2:
1390                 ls_type = tvb_get_ntohl(tvb, offset);
1391                 proto_tree_add_item(ospf_lsr_tree, ospf_filter[OSPFF_LS_TYPE],
1392                                     tvb, offset, 4, FALSE);
1393                 break;
1394             case OSPF_VERSION_3:
1395                 reserved = tvb_get_ntohs(tvb, offset);
1396                 proto_tree_add_text(ospf_lsr_tree, tvb, offset, 2,
1397                     (reserved == 0 ? "Reserved: %u" :  "Reserved: %u [incorrect, should be 0]"), reserved);
1398                 ls_type = tvb_get_ntohs(tvb, offset+2);
1399                 proto_tree_add_text(ospf_lsr_tree, tvb, offset+2, 2, "LS Type: %s (0x%04x)",
1400                             val_to_str(ls_type, v3_ls_type_vals, "Unknown"),
1401                             ls_type);
1402                 break;
1403         }
1404
1405
1406         proto_tree_add_text(ospf_lsr_tree, tvb, offset + 4, 4, "Link State ID: %s",
1407                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
1408         proto_tree_add_item(ospf_lsr_tree, ospf_filter[OSPFF_ADV_ROUTER],
1409                             tvb, offset + 8, 4, FALSE);
1410
1411         offset += 12;
1412     }
1413 }
1414
1415 static void
1416 dissect_ospf_ls_upd(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version,
1417                 guint16 length)
1418 {
1419     proto_tree *ospf_lsa_upd_tree=NULL;
1420     proto_item *ti;
1421     guint32 lsa_nr;
1422     guint32 lsa_counter;
1423
1424     ti = proto_tree_add_text(tree, tvb, offset, length, "LS Update Packet");
1425     ospf_lsa_upd_tree = proto_item_add_subtree(ti, ett_ospf_lsa_upd);
1426
1427     lsa_nr = tvb_get_ntohl(tvb, offset);
1428     proto_tree_add_text(ospf_lsa_upd_tree, tvb, offset, 4, "Number of LSAs: %u",
1429                         lsa_nr);
1430     /* skip to the beginning of the first LSA */
1431     offset += 4; /* the LS Upd Packet contains only a 32 bit #LSAs field */
1432
1433     lsa_counter = 0;
1434     while (lsa_counter < lsa_nr) {
1435         if ( version == OSPF_VERSION_2)
1436             offset = dissect_ospf_v2_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
1437         else
1438             if ( version == OSPF_VERSION_3)
1439                 offset = dissect_ospf_v3_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
1440         lsa_counter += 1;
1441     }
1442 }
1443
1444 static void
1445 dissect_ospf_ls_ack(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version,
1446                 guint16 length)
1447 {
1448     int orig_offset = offset;
1449     /* the body of a LS Ack packet simply contains zero or more LSA Headers */
1450     while (orig_offset + length > offset) {
1451         if ( version == OSPF_VERSION_2)
1452             offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE);
1453         else
1454             if ( version == OSPF_VERSION_3)
1455               offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE);
1456     }
1457 }
1458
1459 /*
1460  * Returns if an LSA is opaque, i.e. requires special treatment
1461  */
1462 static int
1463 is_opaque(int lsa_type)
1464 {
1465     return (lsa_type >= OSPF_LSTYPE_OP_LINKLOCAL &&
1466         lsa_type <= OSPF_LSTYPE_OP_ASWIDE);
1467 }
1468
1469 /* MPLS/TE TLV types */
1470 #define MPLS_TLV_ROUTER    1
1471 #define MPLS_TLV_LINK      2
1472 #define OIF_TLV_TNA    32768
1473
1474 /* MPLS/TE Link STLV types */
1475 enum {
1476     MPLS_LINK_TYPE       = 1,
1477     MPLS_LINK_ID,
1478     MPLS_LINK_LOCAL_IF,
1479     MPLS_LINK_REMOTE_IF,
1480     MPLS_LINK_TE_METRIC,
1481     MPLS_LINK_MAX_BW,
1482     MPLS_LINK_MAX_RES_BW,
1483     MPLS_LINK_UNRES_BW,
1484     MPLS_LINK_COLOR,
1485     MPLS_LINK_LOCAL_REMOTE_ID = 11,
1486     MPLS_LINK_PROTECTION = 14,
1487     MPLS_LINK_IF_SWITCHING_DESC,
1488     MPLS_LINK_SHARED_RISK_GROUP
1489 };
1490
1491 /* OIF TLV types */
1492 enum {
1493     OIF_LOCAL_NODE_ID = 32773,
1494     OIF_REMOTE_NODE_ID,
1495     OIF_SONET_SDH_SWITCHING_CAPABILITY,
1496     OIF_TNA_IPv4_ADDRESS,
1497     OIF_NODE_ID,
1498     OIF_TNA_IPv6_ADDRESS,
1499     OIF_TNA_NSAP_ADDRESS
1500 };
1501
1502 static const value_string mpls_link_stlv_str[] = {
1503     {MPLS_LINK_TYPE, "Link Type"},
1504     {MPLS_LINK_ID, "Link ID"},
1505     {MPLS_LINK_LOCAL_IF, "Local Interface IP Address"},
1506     {MPLS_LINK_REMOTE_IF, "Remote Interface IP Address"},
1507     {MPLS_LINK_TE_METRIC, "Traffic Engineering Metric"},
1508     {MPLS_LINK_MAX_BW, "Maximum Bandwidth"},
1509     {MPLS_LINK_MAX_RES_BW, "Maximum Reservable Bandwidth"},
1510     {MPLS_LINK_UNRES_BW, "Unreserved Bandwidth"},
1511     {MPLS_LINK_COLOR, "Resource Class/Color"},
1512     {MPLS_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier"},
1513     {MPLS_LINK_PROTECTION, "Link Protection Type"},
1514     {MPLS_LINK_IF_SWITCHING_DESC, "Interface Switching Capability Descriptor"},
1515     {MPLS_LINK_SHARED_RISK_GROUP, "Shared Risk Link Group"},
1516     {OIF_LOCAL_NODE_ID, "Local Node ID"},
1517     {OIF_REMOTE_NODE_ID, "Remote Node ID"},
1518     {OIF_SONET_SDH_SWITCHING_CAPABILITY, "Sonet/SDH Interface Switching Capability"},
1519     {0, NULL},
1520 };
1521
1522 static const value_string oif_stlv_str[] = {
1523     {OIF_TNA_IPv4_ADDRESS, "TNA address"},
1524     {OIF_NODE_ID, "Node ID"},
1525     {OIF_TNA_IPv6_ADDRESS, "TNA address"},
1526     {OIF_TNA_NSAP_ADDRESS, "TNA address"},
1527     {0, NULL},
1528 };
1529
1530 /*
1531  * Dissect MPLS/TE opaque LSA
1532  */
1533 static void
1534 dissect_ospf_lsa_mpls(tvbuff_t *tvb, int offset, proto_tree *tree,
1535                       guint32 length)
1536 {
1537     proto_item *ti;
1538     proto_tree *mpls_tree;
1539     proto_tree *tlv_tree;
1540     proto_tree *stlv_tree;
1541     proto_tree *stlv_admingrp_tree = NULL;
1542
1543     int tlv_type;
1544     int tlv_length;
1545     int tlv_end_offset;
1546
1547     int stlv_type, stlv_len, stlv_offset;
1548     const char *stlv_name;
1549     guint32 stlv_admingrp, mask;
1550     int i;
1551     guint8 switch_cap;
1552
1553     ti = proto_tree_add_text(tree, tvb, offset, length,
1554                              "MPLS Traffic Engineering LSA");
1555     proto_tree_add_item_hidden(tree, ospf_filter[OSPFF_LS_MPLS],
1556                                tvb, offset, 2, FALSE);
1557     mpls_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls);
1558
1559     while (length != 0) {
1560         tlv_type = tvb_get_ntohs(tvb, offset);
1561         tlv_length = tvb_get_ntohs(tvb, offset + 2);
1562         tlv_end_offset = offset + tlv_length + 4;
1563
1564         switch (tlv_type) {
1565
1566         case MPLS_TLV_ROUTER:
1567             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
1568                                      "Router Address: %s",
1569                                      ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
1570             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_router);
1571             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 1 - Router Address");
1572             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
1573                                 tlv_length);
1574             proto_tree_add_item(tlv_tree, ospf_filter[OSPFF_LS_MPLS_ROUTERID],
1575                                 tvb, offset+4, 4, FALSE);
1576             break;
1577
1578         case MPLS_TLV_LINK:
1579             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
1580                                      "Link Information");
1581             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
1582             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 2 - Link Information");
1583             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
1584                                 tlv_length);
1585             stlv_offset = offset + 4;
1586
1587             /* Walk down the sub-TLVs for link information */
1588             while (stlv_offset < tlv_end_offset) {
1589                 stlv_type = tvb_get_ntohs(tvb, stlv_offset);
1590                 stlv_len = tvb_get_ntohs(tvb, stlv_offset + 2);
1591                 stlv_name = val_to_str(stlv_type, mpls_link_stlv_str, "Unknown sub-TLV");
1592                 switch (stlv_type) {
1593
1594                 case MPLS_LINK_TYPE:
1595                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1596                                      "%s: %u - %s", stlv_name,
1597                                      tvb_get_guint8(tvb, stlv_offset + 4),
1598                                      val_to_str(tvb_get_guint8(tvb, stlv_offset + 4), 
1599                                         mpls_link_stlv_ltype_str, "Unknown Link Type"));
1600                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1601                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1602                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1603                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1604                                         stlv_len);
1605                     proto_tree_add_item(stlv_tree, ospf_filter[OSPFF_LS_MPLS_LINKTYPE],
1606                                         tvb, stlv_offset+4, 1,FALSE);
1607                     break;
1608
1609                 case MPLS_LINK_ID:
1610                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1611                                              "%s: %s", stlv_name,
1612                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1613                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1614                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1615                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1616                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1617                                         stlv_len);
1618                     proto_tree_add_item(stlv_tree, ospf_filter[OSPFF_LS_MPLS_LINKID],
1619                                         tvb, stlv_offset+4, 4, FALSE);
1620                     break;
1621
1622                 case MPLS_LINK_LOCAL_IF:
1623                 case MPLS_LINK_REMOTE_IF:
1624                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1625                                              "%s", stlv_name);
1626                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1627                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1628                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1629                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1630                                         stlv_len);
1631                     /*   The Local/Remote Interface IP Address sub-TLV is TLV type 3/4, and is 4N
1632                        octets in length, where N is the number of neighbor addresses. */
1633                     for (i=0; i < stlv_len; i+=4)
1634                       proto_tree_add_item(stlv_tree,
1635                                           stlv_type==MPLS_LINK_LOCAL_IF ?
1636                                           ospf_filter[OSPFF_LS_MPLS_LOCAL_ADDR] :
1637                                           ospf_filter[OSPFF_LS_MPLS_REMOTE_ADDR],
1638                                           tvb, stlv_offset+4+i, 4, FALSE);
1639                     break;
1640
1641                 case MPLS_LINK_TE_METRIC:
1642                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1643                                              "%s: %u", stlv_name,
1644                                              tvb_get_ntohl(tvb, stlv_offset + 4));
1645                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1646                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1647                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1648                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1649                                         stlv_len);
1650                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %u", stlv_name,
1651                                         tvb_get_ntohl(tvb, stlv_offset + 4));
1652                     break;
1653
1654                 case MPLS_LINK_COLOR:
1655                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1656                                              "%s: 0x%08x", stlv_name,
1657                                              tvb_get_ntohl(tvb, stlv_offset + 4));
1658                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1659                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1660                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1661                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1662                                         stlv_len);
1663                     stlv_admingrp = tvb_get_ntohl(tvb, stlv_offset + 4);
1664                     mask = 1;
1665                     ti = proto_tree_add_item(stlv_tree, ospf_filter[OSPFF_LS_MPLS_LINKCOLOR],
1666                                         tvb, stlv_offset+4, 4, FALSE);
1667                     stlv_admingrp_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv_admingrp);
1668                     if (stlv_admingrp_tree == NULL)
1669                         return;
1670                     for (i = 0 ; i < 32 ; i++) {
1671                         if ((stlv_admingrp & mask) != 0) {
1672                             proto_tree_add_text(stlv_admingrp_tree, tvb, stlv_offset+4,
1673                                 4, "Group %d", i);
1674                         }
1675                         mask <<= 1;
1676                     }
1677                     break;
1678
1679                 case MPLS_LINK_MAX_BW:
1680                 case MPLS_LINK_MAX_RES_BW:
1681                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1682                                              "%s: %.10g bytes/s (%.0f bits/s)", stlv_name,
1683                                              tvb_get_ntohieee_float(tvb, stlv_offset + 4),
1684                                              tvb_get_ntohieee_float(tvb, stlv_offset + 4) * 8.0);
1685                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1686                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1687                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1688                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1689                                         stlv_len);
1690                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %.10g bytes/s (%.0f bits/s)", stlv_name,
1691                                         tvb_get_ntohieee_float(tvb, stlv_offset + 4),
1692                                         tvb_get_ntohieee_float(tvb, stlv_offset + 4) * 8.0);
1693                     break;
1694
1695                 case MPLS_LINK_UNRES_BW:
1696                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1697                                              "%s", stlv_name);
1698                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1699                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1700                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1701                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1702                                         stlv_len);
1703                     for (i = 0; i < 8; i++) {
1704                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+(i*4), 4,
1705                                             "Pri %d: %.10g bytes/s (%.0f bits/s)", i,
1706                                             tvb_get_ntohieee_float(tvb, stlv_offset + 4 + i*4),
1707                                             tvb_get_ntohieee_float(tvb, stlv_offset + 4 + i*4) * 8.0);
1708                     }
1709                     break;
1710
1711                 case MPLS_LINK_LOCAL_REMOTE_ID:
1712                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1713                                              "%s: %d (0x%x) - %d (0x%x)", stlv_name,
1714                                              tvb_get_ntohl(tvb, stlv_offset + 4),
1715                                              tvb_get_ntohl(tvb, stlv_offset + 4),
1716                                              tvb_get_ntohl(tvb, stlv_offset + 8),
1717                                              tvb_get_ntohl(tvb, stlv_offset + 8));
1718                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1719                     
1720                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1721                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1722                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1723                                         stlv_len);                      
1724                     proto_tree_add_item(stlv_tree,
1725                                         ospf_filter[OSPFF_LS_MPLS_LOCAL_IFID],
1726                                         tvb, stlv_offset+4, 4, FALSE);
1727                     proto_tree_add_item(stlv_tree,
1728                                         ospf_filter[OSPFF_LS_MPLS_REMOTE_IFID],
1729                                         tvb, stlv_offset+8, 4, FALSE);
1730                     break;
1731
1732                 case MPLS_LINK_IF_SWITCHING_DESC:
1733                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1734                                              "%s", stlv_name);
1735                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1736                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1737                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1738                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1739                                         stlv_len);
1740                     switch_cap = tvb_get_guint8 (tvb, stlv_offset+4);
1741                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Switching Type: %s",
1742                                         val_to_str(tvb_get_guint8(tvb,stlv_offset+4),
1743                                                    gmpls_switching_type_str, "Unknown (%d)"));
1744                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+5, 1, "Encoding: %s",
1745                                         val_to_str(tvb_get_guint8(tvb,stlv_offset+5),
1746                                                    gmpls_lsp_enc_str, "Unknown (%d)"));
1747                     for (i = 0; i < 8; i++) {
1748                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+8+(i*4), 4,
1749                                             "Pri %d: %.10g bytes/s (%.0f bits/s)", i,
1750                                             tvb_get_ntohieee_float(tvb, stlv_offset + 8 + i*4),
1751                                             tvb_get_ntohieee_float(tvb, stlv_offset + 8 + i*4) * 8.0);
1752                     }
1753                     if (switch_cap >=1 && switch_cap <=4) {           /* PSC-1 .. PSC-4 */
1754                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+40, 4,
1755                                             "Minimum LSP bandwidth: %.10g bytes/s (%.0f bits/s)",
1756                                             tvb_get_ntohieee_float(tvb, stlv_offset + 40),
1757                                             tvb_get_ntohieee_float(tvb, stlv_offset + 40) * 8.0);
1758                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+44, 2,
1759                                             "Interface MTU: %d", tvb_get_ntohs(tvb, stlv_offset+44));
1760                     }
1761
1762                     if (switch_cap == 100) {                         /* TDM */
1763                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+40, 4,
1764                                             "Minimum LSP bandwidth: %.10g bytes/s (%.0f bits/s)",
1765                                             tvb_get_ntohieee_float(tvb, stlv_offset + 40),
1766                                             tvb_get_ntohieee_float(tvb, stlv_offset + 40) * 8.0);
1767                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+44, 2,
1768                                             "SONET/SDH: %s",
1769                                             tvb_get_guint8(tvb, stlv_offset+44) ?
1770                                             "Arbitrary" : "Standard");
1771                     }
1772                     break;
1773                 case MPLS_LINK_PROTECTION:
1774                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1775                                              "%s", stlv_name);
1776                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1777                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1778                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1779                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1780                                         stlv_len);
1781                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Protection Capability: %s (0x%x)",
1782                                         val_to_str(tvb_get_guint8(tvb,stlv_offset+4), gmpls_protection_cap_str, "Unknown (%d)"),tvb_get_guint8(tvb,stlv_offset+4));
1783                     break;
1784                 
1785                 case MPLS_LINK_SHARED_RISK_GROUP:
1786                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1787                                              "%s", stlv_name);
1788                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1789                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1790                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1791                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1792                                         stlv_len);
1793                     for (i=0; i < stlv_len; i+=4)
1794                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+i, 4, "Shared Risk Link Group: %u", 
1795                                         tvb_get_ntohl(tvb,stlv_offset+4+i)); 
1796                     break;
1797
1798                 case OIF_LOCAL_NODE_ID:
1799                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1800                                              "%s: %s", stlv_name,
1801                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1802                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1803                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1804                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1805                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1806                                         stlv_len);
1807                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "Local Node ID: %s",
1808                                         ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1809                     break;
1810
1811                 case OIF_REMOTE_NODE_ID:
1812                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1813                                              "%s: %s", stlv_name,
1814                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1815                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1816                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1817                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1818                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1819                                         stlv_len);
1820                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "Remote Node ID: %s",
1821                                         ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1822                     break;
1823
1824                 case OIF_SONET_SDH_SWITCHING_CAPABILITY:
1825                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4, "%s", stlv_name);
1826                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1827                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1828                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1829                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1830                                         stlv_len);
1831                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Switching Cap: %s",
1832                                         val_to_str(tvb_get_guint8 (tvb, stlv_offset+4),
1833                                                    gmpls_switching_type_str, "Unknown (%d)"));
1834                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+5, 1, "Encoding: %s",
1835                                         val_to_str(tvb_get_guint8(tvb,stlv_offset+5),
1836                                                    gmpls_lsp_enc_str, "Unknown (%d)"));
1837                     for (i = 0; i < (stlv_len - 4) / 4; i++) {
1838                         proto_tree_add_text(stlv_tree, tvb, stlv_offset+8+(i*4), 4,
1839                                             "%s: %d free timeslots",
1840                                             val_to_str(tvb_get_guint8(tvb, stlv_offset+8+(i*4)),
1841                                                        gmpls_sonet_signal_type_str,
1842                                                        "Unknown Signal Type (%d)"),
1843                                             tvb_get_ntoh24(tvb, stlv_offset + 9 + i*4));
1844                     }
1845
1846                     break;
1847                 default:
1848                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1849                                         "Unknown Link sub-TLV: %u", stlv_type);
1850                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
1851                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1852                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1853                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1854                                         stlv_len);
1855                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, stlv_len,
1856                                         "TLV Value");
1857                     break;
1858                 }
1859                 stlv_offset += ((stlv_len+4+3)/4)*4;
1860             }
1861             break;
1862
1863         case OIF_TLV_TNA:
1864             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
1865                                      "TNA Information");
1866             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_oif_tna);
1867             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 32768 - TNA Information");
1868             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
1869                                 tlv_length);
1870             stlv_offset = offset + 4;
1871
1872             /* Walk down the sub-TLVs for TNA information */
1873             while (stlv_offset < tlv_end_offset) {
1874                 stlv_type = tvb_get_ntohs(tvb, stlv_offset);
1875                 stlv_len = tvb_get_ntohs(tvb, stlv_offset + 2);
1876                 stlv_name = val_to_str(stlv_type, oif_stlv_str, "Unknown sub-TLV");
1877                 switch (stlv_type) {
1878
1879                 case OIF_NODE_ID:
1880                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1881                                              "%s: %s", stlv_name,
1882                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1883                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_oif_tna_stlv);
1884                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1885                                         "TLV Type: %u: %s", stlv_type, stlv_name);
1886                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
1887                                         stlv_len);
1888                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %s", stlv_name,
1889                                         ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
1890                     break;
1891
1892                 case OIF_TNA_IPv4_ADDRESS:
1893                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1894                                              "%s (IPv4): %s", stlv_name,
1895                                              ip_to_str(tvb_get_ptr(tvb, stlv_offset + 8, 4)));
1896                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_oif_tna_stlv);
1897                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1898                                         "TLV Type: %u: %s (IPv4)", stlv_type, stlv_name);
1899                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u", stlv_len);
1900                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Addr Length: %u",
1901                                         tvb_get_guint8 (tvb, stlv_offset+4));
1902                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+8, stlv_len - 4, "TNA Addr: %s",
1903                                         ip_to_str(tvb_get_ptr(tvb, stlv_offset + 8, 4)));
1904                     break;
1905
1906                 case OIF_TNA_IPv6_ADDRESS:
1907                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1908                                              "%s (IPv6): %s", stlv_name,
1909                                              ip6_to_str((const struct e_in6_addr *)
1910                                                          tvb_get_ptr(tvb, stlv_offset + 8, 16)));
1911                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_oif_tna_stlv);
1912                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1913                                         "TLV Type: %u: %s (IPv6)", stlv_type, stlv_name);
1914                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u", stlv_len);
1915                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Addr Length: %u",
1916                                         tvb_get_guint8 (tvb, stlv_offset+4));
1917                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+8, stlv_len - 4, "TNA Addr: %s",
1918                                         ip6_to_str((const struct e_in6_addr *)
1919                                                     tvb_get_ptr(tvb, stlv_offset + 8, 16)));
1920                     break;
1921
1922                 case OIF_TNA_NSAP_ADDRESS:
1923                     ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1924                                              "%s (NSAP): %s", stlv_name,
1925                                              tvb_bytes_to_str (tvb, stlv_offset + 8, stlv_len - 4));
1926                     stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_oif_tna_stlv);
1927                     proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
1928                                         "TLV Type: %u: %s (NSAP)", stlv_type, stlv_name);
1929                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u", stlv_len);
1930                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Addr Length: %u",
1931                                             tvb_get_guint8 (tvb, stlv_offset+4));
1932                     proto_tree_add_text(stlv_tree, tvb, stlv_offset+8, stlv_len - 4, "TNA Addr: %s",
1933                                         tvb_bytes_to_str(tvb, stlv_offset+8, stlv_len - 4));
1934                     break;
1935
1936                 default:
1937                     proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
1938                                         "Unknown Link sub-TLV: %u", stlv_type);
1939                     break;
1940                 }
1941                 stlv_offset += ((stlv_len+4+3)/4)*4;
1942             }
1943             break;
1944         default:
1945             ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
1946                                      "Unknown LSA: %u", tlv_type);
1947             tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
1948             proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: %u - Unknown",
1949                                 tlv_type);
1950             proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
1951                                 tlv_length);
1952             proto_tree_add_text(tlv_tree, tvb, offset+4, tlv_length, "TLV Data");
1953             break;
1954         }
1955
1956         offset += tlv_length + 4;
1957         length -= tlv_length + 4;
1958     }
1959 }
1960
1961 /*
1962  * Dissect opaque LSAs
1963  */
1964 static void
1965 dissect_ospf_lsa_opaque(tvbuff_t *tvb, int offset, proto_tree *tree,
1966                         guint8 ls_id_type, guint32 length)
1967 {
1968     switch (ls_id_type) {
1969
1970     case OSPF_LSA_MPLS_TE:
1971         dissect_ospf_lsa_mpls(tvb, offset, tree, length);
1972         break;
1973
1974     default:
1975         proto_tree_add_text(tree, tvb, offset, length,
1976                             "Unknown LSA Type %u", ls_id_type);
1977         break;
1978     } /* switch on opaque LSA id */
1979 }
1980
1981 static int
1982 dissect_ospf_v2_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
1983                  gboolean disassemble_body)
1984 {
1985     proto_tree *ospf_lsa_tree;
1986     proto_item *ti;
1987
1988     guint8               ls_type;
1989     guint16              ls_length;
1990     int                  end_offset;
1991     guint16              nr_links;
1992     guint16              nr_tos;
1993
1994     /* router LSA */
1995     guint8               link_type;
1996     guint16              link_counter;
1997     guint8               tos_counter;
1998     const char          *link_type_str;
1999     const char          *link_type_short_str;
2000     const char          *link_id;
2001
2002     /* AS-external LSA */
2003     guint8               options;
2004
2005     /* opaque LSA */
2006     guint8               ls_id_type;
2007
2008     ls_type = tvb_get_guint8(tvb, offset + 3);
2009     ls_length = tvb_get_ntohs(tvb, offset + 18);
2010     end_offset = offset + ls_length;
2011
2012     if (disassemble_body) {
2013         ti = proto_tree_add_text(tree, tvb, offset, ls_length,
2014                                  "LS Type: %s",
2015                                  val_to_str(ls_type, ls_type_vals, "Unknown (%d)"));
2016     } else {
2017         ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
2018                                  "LSA Header");
2019     }
2020     ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
2021
2022     proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
2023                         tvb_get_ntohs(tvb, offset));
2024     dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset + 2, &bfinfo_v2_options);
2025     proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_LS_TYPE], tvb,
2026                         offset + 3, 1, FALSE);
2027     proto_tree_add_item_hidden(ospf_lsa_tree,
2028                                ospf_filter[ospf_ls_type_to_filter(ls_type)], tvb,
2029                                offset + 3, 1, FALSE);
2030
2031     if (is_opaque(ls_type)) {
2032         ls_id_type = tvb_get_guint8(tvb, offset + 4);
2033         proto_tree_add_uint(ospf_lsa_tree, ospf_filter[OSPFF_LS_OPAQUE_TYPE],
2034                             tvb, offset + 4, 1, ls_id_type);
2035
2036         switch (ls_id_type) {
2037
2038         case OSPF_LSA_MPLS_TE:
2039             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 1, "Link State ID TE-LSA Reserved: %u",
2040                                 tvb_get_guint8(tvb, offset + 5));
2041             proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_LS_MPLS_TE_INSTANCE],
2042                                 tvb, offset + 6, 2, FALSE);
2043             break;
2044
2045         default:
2046             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3, "Link State ID Opaque ID: %u",
2047                                 tvb_get_ntoh24(tvb, offset + 5));
2048             break;
2049         }
2050     } else {
2051         ls_id_type = 0;
2052         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
2053                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
2054     }
2055
2056     proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_ADV_ROUTER],
2057                         tvb, offset + 8, 4, FALSE);
2058     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%08x",
2059                         tvb_get_ntohl(tvb, offset + 12));
2060     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
2061                         tvb_get_ntohs(tvb, offset + 16));
2062
2063     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
2064                         ls_length);
2065
2066     /* skip past the LSA header to the body */
2067     offset += OSPF_LSA_HEADER_LENGTH;
2068     if (ls_length <= OSPF_LSA_HEADER_LENGTH)
2069         return offset;  /* no data, or bogus length */
2070     ls_length -= OSPF_LSA_HEADER_LENGTH;
2071
2072     if (!disassemble_body)
2073         return offset;
2074
2075     switch (ls_type){
2076
2077     case OSPF_LSTYPE_ROUTER:
2078         /* flags field in an router-lsa */
2079         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset, &bfinfo_v2_router_lsa_flags);
2080
2081         nr_links = tvb_get_ntohs(tvb, offset + 2);
2082         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "Number of Links: %u",
2083                             nr_links);
2084         offset += 4;
2085         /* nr_links links follow
2086          * maybe we should put each of the links into its own subtree ???
2087          */
2088         for (link_counter = 1; link_counter <= nr_links; link_counter++) {
2089             proto_tree *ospf_lsa_router_link_tree;
2090             proto_item *ti_local;
2091
2092
2093             /* check the Link Type and ID */
2094             link_type = tvb_get_guint8(tvb, offset + 8);
2095             switch (link_type) {
2096
2097             case OSPF_LINK_PTP:
2098                 link_type_str="Point-to-point connection to another router";
2099                 link_type_short_str="PTP";
2100                 link_id="Neighboring router's Router ID";
2101                 break;
2102
2103             case OSPF_LINK_TRANSIT:
2104                 link_type_str="Connection to a transit network";
2105                 link_type_short_str="Transit";
2106                 link_id="IP address of Designated Router";
2107                 break;
2108
2109             case OSPF_LINK_STUB:
2110                 link_type_str="Connection to a stub network";
2111                 link_type_short_str="Stub";
2112                 link_id="IP network/subnet number";
2113                 break;
2114
2115             case OSPF_LINK_VIRTUAL:
2116                 link_type_str="Virtual link";
2117                 link_type_short_str="Virtual";
2118                 link_id="Neighboring router's Router ID";
2119                 break;
2120
2121             default:
2122                 link_type_str="Unknown link type";
2123                 link_type_short_str="Unknown";
2124                 link_id="Unknown link ID";
2125                 break;
2126             }
2127
2128             nr_tos = tvb_get_guint8(tvb, offset + 9);
2129
2130             
2131             ti_local = proto_tree_add_text(ospf_lsa_tree, tvb, offset, 12 + 4 * nr_tos,
2132                                      "Type: %-8s ID: %-15s Data: %-15s Metric: %d",
2133                                      link_type_short_str, 
2134                                      ip_to_str(tvb_get_ptr(tvb, offset, 4)),
2135                                      ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)),
2136                                      tvb_get_ntohs(tvb, offset + 10));
2137
2138             ospf_lsa_router_link_tree = proto_item_add_subtree(ti_local, ett_ospf_lsa_router_link);
2139
2140             proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset, 4, "%s: %s", link_id,
2141                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2142
2143             /* link_data should be specified in detail (e.g. network mask) (depends on link type)*/
2144             proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 4, 4, "Link Data: %s",
2145                                 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
2146
2147             proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 8, 1, "Link Type: %u - %s",
2148                                 link_type, link_type_str);
2149             proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 9, 1, "Number of TOS metrics: %u",
2150                                 nr_tos);
2151             proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 10, 2, "TOS 0 metric: %u",
2152                                 tvb_get_ntohs(tvb, offset + 10));
2153
2154             offset += 12;
2155
2156             /* nr_tos metrics may follow each link
2157              * ATTENTION: TOS metrics are not tested (I don't have TOS
2158              * based routing)
2159              * please send me a mail if it is/isn't working
2160              */
2161             for (tos_counter = 1; tos_counter <= nr_tos; tos_counter++) {
2162                 proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
2163                                     tvb_get_guint8(tvb, offset),
2164                                     tvb_get_ntohs(tvb, offset + 2));
2165                 offset += 4;
2166             }
2167         }
2168         break;
2169
2170     case OSPF_LSTYPE_NETWORK:
2171         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
2172                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2173         offset += 4;
2174
2175         while (offset < end_offset) {
2176             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
2177                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2178             offset += 4;
2179         }
2180         break;
2181
2182     case OSPF_LSTYPE_SUMMERY:
2183     /* Type 3 and 4 LSAs have the same format */
2184     case OSPF_LSTYPE_ASBR:
2185         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
2186                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2187         offset += 4;
2188
2189         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Metric: %u",
2190                             tvb_get_ntoh24(tvb, offset + 1));
2191         offset += 4;
2192
2193         /* TOS-specific information, if any */
2194         while (offset < end_offset) {
2195             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
2196                                 tvb_get_guint8(tvb, offset),
2197                                 tvb_get_ntoh24(tvb, offset + 1));
2198             offset += 4;
2199         }
2200         break;
2201
2202     case OSPF_LSTYPE_ASEXT:
2203     case OSPF_LSTYPE_ASEXT7:
2204         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
2205                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2206         offset += 4;
2207
2208         options = tvb_get_guint8(tvb, offset);
2209         if (options & 0x80) { /* check wether or not E bit is set */
2210             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2211                     "External Type: Type 2 (metric is larger than any other link state path)");
2212         } else {
2213             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2214                     "External Type: Type 1 (metric is specified in the same units as interface cost)");
2215         }
2216         /* the metric field of a AS-external LAS is specified in 3 bytes */
2217         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3, "Metric: %u",
2218                             tvb_get_ntoh24(tvb, offset + 1));
2219         offset += 4;
2220
2221         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
2222                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2223         offset += 4;
2224
2225         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
2226                             tvb_get_ntohl(tvb, offset));
2227         offset += 4;
2228
2229         /* TOS-specific information, if any */
2230         while (offset < end_offset) {
2231             options = tvb_get_guint8(tvb, offset);
2232             if (options & 0x80) { /* check wether or not E bit is set */
2233                 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2234                         "External Type: Type 2 (metric is larger than any other link state path)");
2235             } else {
2236                 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2237                         "External Type: Type 1 (metric is specified in the same units as interface cost)");
2238             }
2239             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
2240                                 options & 0x7F,
2241                                 tvb_get_ntoh24(tvb, offset + 1));
2242             offset += 4;
2243
2244             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
2245                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2246             offset += 4;
2247
2248             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
2249                                 tvb_get_ntohl(tvb, offset));
2250             offset += 4;
2251         }
2252         break;
2253
2254     case OSPF_LSTYPE_OP_LINKLOCAL:
2255     case OSPF_LSTYPE_OP_AREALOCAL:
2256     case OSPF_LSTYPE_OP_ASWIDE:
2257         /*
2258          * RFC 2370 opaque LSAs.
2259          */
2260         dissect_ospf_lsa_opaque(tvb, offset, ospf_lsa_tree, ls_id_type,
2261                                 ls_length);
2262         offset += ls_length;
2263         break;
2264
2265     default:
2266         /* unknown LSA type */
2267         proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
2268                             "Unknown LSA Type");
2269         offset += ls_length;
2270         break;
2271     }
2272     /* return the offset of the next LSA */
2273     return offset;
2274 }
2275
2276 static int
2277 dissect_ospf_v3_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
2278                  gboolean disassemble_body)
2279 {
2280     proto_tree *ospf_lsa_tree;
2281     proto_item *ti;
2282
2283     guint16              ls_type;
2284     guint16              ls_length;
2285     int                  end_offset;
2286     guint8               reserved;
2287
2288     /* router LSA */
2289     guint8               link_type;
2290     const char          *link_type_str;
2291     guint32              metric;
2292
2293     guint8               router_priority;
2294     guint32              number_prefixes;
2295     guint8               prefix_length;
2296     guint16              reserved16;
2297
2298     guint16              referenced_ls_type;
2299
2300     guint8               flags;
2301     guint32              external_route_tag;
2302
2303
2304     ls_type = tvb_get_ntohs(tvb, offset + 2);
2305     ls_length = tvb_get_ntohs(tvb, offset + 18);
2306     end_offset = offset + ls_length;
2307
2308     if (disassemble_body) {
2309         ti = proto_tree_add_text(tree, tvb, offset, ls_length,
2310                                  "%s (Type: 0x%04x)", val_to_str(ls_type, v3_ls_type_vals,"Unknown"), ls_type);
2311     } else {
2312         ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
2313                                  "LSA Header");
2314     }
2315     ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
2316
2317     proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
2318                         tvb_get_ntohs(tvb, offset));
2319
2320     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "LSA Type: 0x%04x (%s)",
2321                         ls_type, val_to_str(ls_type, v3_ls_type_vals,"Unkown"));
2322
2323     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
2324                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
2325
2326     proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_ADV_ROUTER],
2327                         tvb, offset + 8, 4, FALSE);
2328     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%08x",
2329                         tvb_get_ntohl(tvb, offset + 12));
2330     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
2331                         tvb_get_ntohs(tvb, offset + 16));
2332
2333     proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
2334                         ls_length);
2335
2336     /* skip past the LSA header to the body */
2337     offset += OSPF_LSA_HEADER_LENGTH;
2338     ls_length -= OSPF_LSA_HEADER_LENGTH;
2339
2340     if (!disassemble_body)
2341         return offset;
2342
2343     switch (ls_type){
2344
2345
2346     case OSPF_V3_LSTYPE_ROUTER:
2347         /* flags field in an router-lsa */
2348         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset, &bfinfo_v3_router_lsa_flags);
2349
2350         /* options field in an router-lsa */
2351         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset + 1, &bfinfo_v3_options);
2352
2353         /* skip the router-lsa flags and options */
2354         offset+=4;
2355         ls_length-=4;
2356
2357         if (ls_length > 0)
2358              proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
2359                    "Router Interfaces:");
2360
2361         /* scan all router-lsa router interfaces */
2362         /* maybe we should put each of the links into its own subtree ??? */
2363         while (ls_length > 0 ) {
2364
2365             /* check the type */
2366             link_type = tvb_get_guint8(tvb, offset);
2367             switch (link_type) {
2368
2369                 case OSPF_V3_LINK_PTP:
2370                     link_type_str="Point-to-point connection to another router";
2371                     break;
2372
2373                 case OSPF_V3_LINK_TRANSIT:
2374                     link_type_str="Connection to a transit network";
2375                     break;
2376
2377                 case OSPF_V3_LINK_RESERVED:
2378                     link_type_str="Connection to a stub network";
2379                     break;
2380
2381                 case OSPF_V3_LINK_VIRTUAL:
2382                     link_type_str="Virtual link";
2383                     break;
2384
2385                 default:
2386                     link_type_str="Unknown link type";
2387                     break;
2388             }
2389
2390             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Type: %u (%s)", link_type,link_type_str);
2391
2392             /* reserved field */
2393             reserved = tvb_get_guint8(tvb, offset+1);
2394             proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 1,
2395                (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved);
2396
2397             /* metric */
2398             metric=tvb_get_ntohs(tvb, offset+2);
2399             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2,"Metric: %u",metric);
2400
2401             /* Interface ID */
2402             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Interface ID: %u",
2403                         tvb_get_ntohl(tvb, offset + 4));
2404
2405             /* Neighbor Interface ID */
2406             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Neighbor Interface ID: %u",
2407                         tvb_get_ntohl(tvb, offset + 8));
2408
2409             /* Neighbor Router ID */
2410             proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "Neighbor Router ID: %s",
2411                 ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
2412
2413             /* skip to the (possible) next entry */
2414             offset+=16;
2415             ls_length-=16;
2416
2417         }
2418         break;
2419
2420     case OSPF_V3_LSTYPE_NETWORK:
2421
2422         /* reserved field */
2423         reserved = tvb_get_guint8(tvb, offset);
2424         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2425                (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved);
2426
2427         /* options field in an network-lsa */
2428         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset + 1, &bfinfo_v3_options);
2429
2430         offset += 4;
2431         ls_length-=4;
2432
2433         while (ls_length > 0 ) {
2434             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
2435                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2436             ls_length-=4;
2437             offset += 4;
2438         }
2439         break;
2440
2441
2442     case OSPF_V3_LSTYPE_INTER_AREA_PREFIX:
2443
2444         /* reserved field */
2445         reserved = tvb_get_guint8(tvb, offset);
2446         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2447                (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved);
2448
2449         /* metric */
2450         metric=tvb_get_ntoh24(tvb, offset+1);
2451         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3,"Metric: %u",metric);
2452
2453         /* prefix length */
2454         prefix_length=tvb_get_guint8(tvb, offset+4);
2455         proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length);
2456
2457         /* prefix options */
2458         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset+5, &bfinfo_v3_prefix_options);
2459
2460         /* 16 bits reserved */
2461         reserved16=tvb_get_ntohs(tvb, offset+6);
2462         proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,
2463                (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved16);
2464
2465         offset+=8;
2466
2467         /* address_prefix */
2468         dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
2469
2470         offset+=(prefix_length+31)/32*4;
2471
2472         break;
2473
2474
2475     case OSPF_V3_LSTYPE_INTER_AREA_ROUTER:
2476
2477         /* reserved field */
2478         reserved = tvb_get_guint8(tvb, offset);
2479         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
2480                (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved);
2481
2482         /* options field in an inter-area-router-lsa */
2483         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset + 1, &bfinfo_v3_options);
2484
2485         /* reserved field */
2486         reserved = tvb_get_guint8(tvb, offset+4);
2487         proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1,
2488                (reserved == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved);
2489
2490         /* metric */
2491         metric=tvb_get_ntoh24(tvb, offset+5);
2492         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3,"Metric: %u",metric);
2493
2494         /* Destination Router ID */
2495         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Destination Router ID: %s",
2496                 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
2497
2498         offset+=12;
2499         break;
2500
2501
2502     case OSPF_V3_LSTYPE_TYPE_7:
2503     case OSPF_V3_LSTYPE_AS_EXTERNAL:
2504
2505         /* flags */
2506         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset, &bfinfo_v3_as_external_flags);
2507         flags=tvb_get_guint8(tvb, offset);
2508
2509         /* 24 bits metric */
2510         metric=tvb_get_ntoh24(tvb, offset+1);
2511         proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 3,
2512                                 "Metric: %u", metric);
2513
2514         /* prefix length */
2515         prefix_length=tvb_get_guint8(tvb, offset+4);
2516         proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length);
2517
2518         /* prefix options */
2519         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset+5, &bfinfo_v3_prefix_options);
2520
2521         /* referenced LS type */
2522         referenced_ls_type=tvb_get_ntohs(tvb, offset+6);
2523         proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,"Referenced LS type 0x%04x (%s)",
2524                             referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
2525
2526         offset+=8;
2527
2528         /* address_prefix */
2529         dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
2530
2531         offset+=(prefix_length+31)/32*4;
2532
2533         /* Forwarding Address (optional - only if F-flag is on) */
2534         if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_F) ) {
2535             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 16,"Forwarding Address: %s",
2536               ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16)));
2537
2538             offset+=16;
2539         }
2540
2541         /* External Route Tag (optional - only if T-flag is on) */
2542         if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_T) ) {
2543             external_route_tag=tvb_get_ntohl(tvb, offset);
2544             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4,"External Route Tag: %u",
2545                                 external_route_tag);
2546
2547             offset+=4;
2548         }
2549
2550         /* Referenced Link State ID (optional - only if Referenced LS type is non-zero */
2551         if ( (offset < end_offset) && (referenced_ls_type != 0) ) {
2552             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Referenced Link State ID: %s",
2553                             ip_to_str(tvb_get_ptr(tvb, offset, 4)));
2554             offset+=4;
2555         }
2556
2557         break;
2558
2559     case OSPF_V3_LSTYPE_LINK:
2560
2561         /* router priority */
2562         router_priority=tvb_get_guint8(tvb, offset);
2563         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Router Priority: %u", router_priority);
2564
2565         /* options field in an link-lsa */
2566         dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset + 1, &bfinfo_v3_options);
2567
2568         /* Link-local Interface Address */
2569         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 16, "Link-local Interface Address: %s",
2570            ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 4, 16)));
2571
2572         /* Number prefixes */
2573         number_prefixes=tvb_get_ntohl(tvb, offset + 20);
2574         proto_tree_add_text(ospf_lsa_tree, tvb, offset+20, 4, "# prefixes: %d",number_prefixes);
2575
2576         offset+=24;
2577
2578         while (number_prefixes > 0) {
2579
2580             /* prefix length */
2581             prefix_length=tvb_get_guint8(tvb, offset);
2582             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length);
2583
2584             /* prefix options */
2585             dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset+1, &bfinfo_v3_prefix_options);
2586
2587             /* 16 bits reserved */
2588             reserved16=tvb_get_ntohs(tvb, offset+2);
2589             proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,
2590                (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u [incorrect, should be 0]"),reserved16);
2591
2592             offset+=4;
2593
2594             /* address_prefix */
2595             dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
2596
2597             offset+=(prefix_length+31)/32*4;
2598
2599             number_prefixes--;
2600
2601         }
2602         break;
2603
2604     case OSPF_V3_LSTYPE_INTRA_AREA_PREFIX:
2605
2606         /* # prefixes */
2607         number_prefixes=tvb_get_ntohs(tvb, offset);
2608         proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2,"# prefixes: %u",number_prefixes);
2609
2610         /* referenced LS type */
2611         referenced_ls_type=tvb_get_ntohs(tvb, offset+2);
2612         proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,"Referenced LS type 0x%04x (%s)",
2613                             referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
2614
2615         /* Referenced Link State ID */
2616         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Referenced Link State ID: %s",
2617                             ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
2618
2619         /* Referenced Advertising Router */
2620         proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Referenced Advertising Router: %s",
2621                             ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
2622
2623         offset+=12;
2624
2625         while (number_prefixes > 0) {
2626
2627             /* prefix length */
2628             prefix_length=tvb_get_guint8(tvb, offset);
2629             proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length);
2630
2631             /* prefix options */
2632             dissect_ospf_bitfield(ospf_lsa_tree, tvb, offset+1, &bfinfo_v3_prefix_options);
2633
2634             /* 16 bits metric */
2635             metric=tvb_get_ntohs(tvb, offset+2);
2636             proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,
2637                                 "Metric: %u", metric);
2638
2639             offset+=4;
2640
2641             /* address_prefix */
2642             dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
2643
2644             offset+=(prefix_length+31)/32*4;
2645
2646             number_prefixes--;
2647         }
2648         break;
2649
2650     default:
2651         /* unknown LSA type */
2652         proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
2653                             "Unknown LSA Type 0x%04x",ls_type);
2654         offset += ls_length;
2655         break;
2656     }
2657     /* return the offset of the next LSA */
2658     return offset;
2659 }
2660
2661 static void dissect_ospf_v3_address_prefix(tvbuff_t *tvb, int offset, int prefix_length, proto_tree *tree)
2662 {
2663
2664     int bytes_to_process;
2665     struct e_in6_addr prefix;
2666
2667     bytes_to_process=((prefix_length+31)/32)*4;
2668
2669     if (prefix_length > 128) {
2670         proto_tree_add_text(tree, tvb, offset, bytes_to_process,
2671             "Address Prefix: length is invalid (%d, should be <= 128)",
2672             prefix_length);
2673         return;
2674     }
2675
2676     memset(prefix.bytes, 0, sizeof prefix.bytes);
2677     if (bytes_to_process != 0) {
2678         tvb_memcpy(tvb, prefix.bytes, offset, bytes_to_process);
2679         if (prefix_length % 8) {
2680             prefix.bytes[bytes_to_process - 1] &=
2681                 ((0xff00 >> (prefix_length % 8)) & 0xff);
2682         }
2683     }
2684     proto_tree_add_text(tree, tvb, offset, bytes_to_process,
2685         "Address Prefix: %s", ip6_to_str(&prefix));
2686
2687 }
2688
2689
2690 void
2691 proto_register_ospf(void)
2692 {
2693     static gint *ett[] = {
2694         &ett_ospf,
2695         &ett_ospf_hdr,
2696         &ett_ospf_hello,
2697         &ett_ospf_desc,
2698         &ett_ospf_lsr,
2699         &ett_ospf_lsa,
2700         &ett_ospf_lsa_router_link,
2701         &ett_ospf_lsa_upd,
2702         &ett_ospf_lsa_mpls,
2703         &ett_ospf_lsa_mpls_router,
2704         &ett_ospf_lsa_mpls_link,
2705         &ett_ospf_lsa_mpls_link_stlv,
2706         &ett_ospf_lsa_mpls_link_stlv_admingrp,
2707         &ett_ospf_lsa_oif_tna,
2708         &ett_ospf_lsa_oif_tna_stlv,
2709         &ett_ospf_v2_options,
2710         &ett_ospf_v3_options,
2711         &ett_ospf_dbd,
2712         &ett_ospf_lls_data_block,
2713         &ett_ospf_lls_tlv,
2714         &ett_ospf_lls_ext_options,
2715         &ett_ospf_v2_router_lsa_flags,
2716         &ett_ospf_v3_router_lsa_flags,
2717         &ett_ospf_v3_as_external_flags,
2718         &ett_ospf_v3_prefix_options
2719     };
2720
2721     proto_ospf = proto_register_protocol("Open Shortest Path First",
2722                                          "OSPF", "ospf");
2723     proto_register_field_array(proto_ospf, ospff_info, array_length(ospff_info));
2724     proto_register_subtree_array(ett, array_length(ett));
2725 }
2726
2727 void
2728 proto_reg_handoff_ospf(void)
2729 {
2730     dissector_handle_t ospf_handle;
2731
2732     ospf_handle = create_dissector_handle(dissect_ospf, proto_ospf);
2733     dissector_add("ip.proto", IP_PROTO_OSPF, ospf_handle);
2734     data_handle = find_dissector("data");
2735 }