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