2 * Routines for OSPF packet disassembly
3 * (c) Copyright Hannes R. Boehm <hannes@boehm.org>
5 * $Id: packet-ospf.c,v 1.53 2001/12/10 00:25:31 guy Exp $
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>
14 * TOS - support is not fully implemented
16 * Ethereal - Network traffic analyzer
17 * By Gerald Combs <gerald@ethereal.com>
18 * Copyright 1998 Gerald Combs
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
43 #ifdef HAVE_NETINET_IN_H
44 # include <netinet/in.h>
54 #include "ieee-float.h"
56 #define OSPF_VERSION_2 2
57 #define OSPF_VERSION_3 3
58 #define OSPF_VERSION_2_HEADER_LENGTH 24
59 #define OSPF_VERSION_3_HEADER_LENGTH 16
63 #define OSPF_DB_DESC 2
68 static const value_string pt_vals[] = {
69 {OSPF_HELLO, "Hello Packet" },
70 {OSPF_DB_DESC, "DB Descr." },
71 {OSPF_LS_REQ, "LS Request" },
72 {OSPF_LS_UPD, "LS Update" },
73 {OSPF_LS_ACK, "LS Acknowledge" },
77 #define OSPF_AUTH_NONE 0
78 #define OSPF_AUTH_SIMPLE 1
79 #define OSPF_AUTH_CRYPT 2
81 static const value_string auth_vals[] = {
82 {OSPF_AUTH_NONE, "Null" },
83 {OSPF_AUTH_SIMPLE, "Simple password" },
84 {OSPF_AUTH_CRYPT, "Cryptographic" },
88 #define OSPF_V2_OPTIONS_E 0x02
89 #define OSPF_V2_OPTIONS_MC 0x04
90 #define OSPF_V2_OPTIONS_NP 0x08
91 #define OSPF_V2_OPTIONS_EA 0x10
92 #define OSPF_V2_OPTIONS_DC 0x20
93 #define OSPF_V2_OPTIONS_O 0x40
94 #define OSPF_V2_OPTIONS_DN 0x01
95 #define OSPF_V3_OPTIONS_V6 0x01
96 #define OSPF_V3_OPTIONS_E 0x02
97 #define OSPF_V3_OPTIONS_MC 0x04
98 #define OSPF_V3_OPTIONS_N 0x08
99 #define OSPF_V3_OPTIONS_R 0x10
100 #define OSPF_V3_OPTIONS_DC 0x20
103 #define OSPF_DBD_FLAG_MS 1
104 #define OSPF_DBD_FLAG_M 2
105 #define OSPF_DBD_FLAG_I 4
107 #define OSPF_LS_REQ_LENGTH 12
109 #define OSPF_LSTYPE_ROUTER 1
110 #define OSPF_LSTYPE_NETWORK 2
111 #define OSPF_LSTYPE_SUMMERY 3
112 #define OSPF_LSTYPE_ASBR 4
113 #define OSPF_LSTYPE_ASEXT 5
114 #define OSPF_LSTYPE_GRPMEMBER 6
115 #define OSPF_LSTYPE_ASEXT7 7
116 #define OSPF_LSTYPE_EXTATTR 8
117 #define OSPF_V3_LSTYPE_ROUTER 0x2001
118 #define OSPF_V3_LSTYPE_NETWORK 0x2002
119 #define OSPF_V3_LSTYPE_INTER_AREA_PREFIX 0x2003
120 #define OSPF_V3_LSTYPE_INTER_AREA_ROUTER 0x2004
121 #define OSPF_V3_LSTYPE_AS_EXTERNAL 0x4005
122 #define OSPF_V3_LSTYPE_GROUP_MEMBERSHIP 0x2006
123 #define OSPF_V3_LSTYPE_TYPE_7 0x2007
124 #define OSPF_V3_LSTYPE_LINK 0x0008
125 #define OSPF_V3_LSTYPE_INTRA_AREA_PREFIX 0x2009
127 /* Opaque LSA types */
128 #define OSPF_LSTYPE_OP_LINKLOCAL 9
129 #define OSPF_LSTYPE_OP_AREALOCAL 10
130 #define OSPF_LSTYPE_OP_ASWIDE 11
132 #define OSPF_LINK_PTP 1
133 #define OSPF_LINK_TRANSIT 2
134 #define OSPF_LINK_STUB 3
135 #define OSPF_LINK_VIRTUAL 4
137 #define OSPF_V3_LINK_PTP 1
138 #define OSPF_V3_LINK_TRANSIT 2
139 #define OSPF_V3_LINK_RESERVED 3
140 #define OSPF_V3_LINK_VIRTUAL 4
142 #define OSPF_LSA_HEADER_LENGTH 20
144 /* Known opaque LSAs */
145 #define OSPF_LSA_MPLS_TE 1
148 static const value_string ls_type_vals[] = {
149 {OSPF_LSTYPE_ROUTER, "Router-LSA" },
150 {OSPF_LSTYPE_NETWORK, "Network-LSA" },
151 {OSPF_LSTYPE_SUMMERY, "Summary-LSA (IP network)" },
152 {OSPF_LSTYPE_ASBR, "Summary-LSA (ASBR)" },
153 {OSPF_LSTYPE_ASEXT, "AS-External-LSA (ASBR)" },
154 {OSPF_LSTYPE_GRPMEMBER, "Group Membership LSA" },
155 {OSPF_LSTYPE_ASEXT7, "NSSA AS-External-LSA" },
156 {OSPF_LSTYPE_EXTATTR, "External Attributes LSA" },
157 {OSPF_LSTYPE_OP_LINKLOCAL, "Opaque LSA, Link-local scope" },
158 {OSPF_LSTYPE_OP_AREALOCAL, "Opaque LSA, Area-local scope" },
163 static const value_string v3_ls_type_vals[] = {
164 {OSPF_V3_LSTYPE_ROUTER, "Router-LSA" },
165 {OSPF_V3_LSTYPE_NETWORK, "Network-LSA" },
166 {OSPF_V3_LSTYPE_INTER_AREA_PREFIX, "Inter-Area-Prefix-LSA" },
167 {OSPF_V3_LSTYPE_INTER_AREA_ROUTER, "Inter-Area-Router-LSA" },
168 {OSPF_V3_LSTYPE_AS_EXTERNAL, "AS-External-LSA" },
169 {OSPF_V3_LSTYPE_GROUP_MEMBERSHIP, "Group-Membership-LSA" },
170 {OSPF_V3_LSTYPE_TYPE_7, "Type-LSA" },
171 {OSPF_V3_LSTYPE_LINK, "Link-LSA" },
172 {OSPF_V3_LSTYPE_INTRA_AREA_PREFIX, "Intra-Area-Prefix-LSA" },
178 #define OSPF_V3_ROUTER_LSA_FLAG_B 0x01
179 #define OSPF_V3_ROUTER_LSA_FLAG_E 0x02
180 #define OSPF_V3_ROUTER_LSA_FLAG_V 0x04
181 #define OSPF_V3_ROUTER_LSA_FLAG_W 0x08
183 #define OSPF_V3_PREFIX_OPTION_NU 0x01
184 #define OSPF_V3_PREFIX_OPTION_LA 0x02
185 #define OSPF_V3_PREFIX_OPTION_MC 0x04
186 #define OSPF_V3_PREFIX_OPTION_P 0x08
188 #define OSPF_V3_AS_EXTERNAL_FLAG_T 0x01
189 #define OSPF_V3_AS_EXTERNAL_FLAG_F 0x02
190 #define OSPF_V3_AS_EXTERNAL_FLAG_E 0x04
193 static int proto_ospf = -1;
195 static gint ett_ospf = -1;
196 static gint ett_ospf_hdr = -1;
197 static gint ett_ospf_hello = -1;
198 static gint ett_ospf_desc = -1;
199 static gint ett_ospf_lsr = -1;
200 static gint ett_ospf_lsa = -1;
201 static gint ett_ospf_lsa_upd = -1;
203 /* Trees for opaque LSAs */
204 static gint ett_ospf_lsa_mpls = -1;
205 static gint ett_ospf_lsa_mpls_router = -1;
206 static gint ett_ospf_lsa_mpls_link = -1;
207 static gint ett_ospf_lsa_mpls_link_stlv = -1;
209 static dissector_handle_t data_handle;
211 static void dissect_ospf_hello(tvbuff_t*, int, proto_tree*, guint8);
212 static void dissect_ospf_db_desc(tvbuff_t*, int, proto_tree*, guint8);
213 static void dissect_ospf_ls_req(tvbuff_t*, int, proto_tree*, guint8);
214 static void dissect_ospf_ls_upd(tvbuff_t*, int, proto_tree*, guint8);
215 static void dissect_ospf_ls_ack(tvbuff_t*, int, proto_tree*, guint8);
217 /* dissect_ospf_v[23]lsa returns the offset of the next LSA
218 * if disassemble_body is set to FALSE (e.g. in LSA ACK
219 * packets), the offset is set to the offset of the next
222 static int dissect_ospf_v2_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body);
223 static int dissect_ospf_v3_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body);
225 static void dissect_ospf_options(tvbuff_t *, int, proto_tree *, guint8);
227 static void dissect_ospf_v3_prefix_options(tvbuff_t *, int, proto_tree *);
229 static void dissect_ospf_v3_address_prefix(tvbuff_t *, int, int, proto_tree *);
232 dissect_ospf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
234 proto_tree *ospf_tree = NULL;
236 proto_tree *ospf_header_tree;
243 guint16 cksum, computed_cksum;
244 guint length, reported_length;
248 unsigned int ospf_header_length;
254 if (check_col(pinfo->cinfo, COL_PROTOCOL))
255 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OSPF");
256 if (check_col(pinfo->cinfo, COL_INFO))
257 col_clear(pinfo->cinfo, COL_INFO);
259 version = tvb_get_guint8(tvb, 0);
262 ospf_header_length = OSPF_VERSION_2_HEADER_LENGTH;
265 ospf_header_length = OSPF_VERSION_3_HEADER_LENGTH;
268 ospf_header_length = 0;
272 packet_type = tvb_get_guint8(tvb, 1);
273 if (check_col(pinfo->cinfo, COL_INFO)) {
274 col_add_str(pinfo->cinfo, COL_INFO,
275 val_to_str(packet_type, pt_vals, "Unknown (%u)"));
279 ospflen = tvb_get_ntohs(tvb, 2);
281 ti = proto_tree_add_item(tree, proto_ospf, tvb, 0, ospflen, FALSE);
282 ospf_tree = proto_item_add_subtree(ti, ett_ospf);
284 ti = proto_tree_add_text(ospf_tree, tvb, 0, ospf_header_length,
286 ospf_header_tree = proto_item_add_subtree(ti, ett_ospf_hdr);
288 proto_tree_add_text(ospf_header_tree, tvb, 0, 1, "OSPF Version: %u",
290 proto_tree_add_text(ospf_header_tree, tvb, 1, 1, "OSPF Packet Type: %u (%s)",
292 val_to_str(packet_type, pt_vals, "Unknown"));
293 proto_tree_add_text(ospf_header_tree, tvb, 2, 2, "Packet Length: %u",
295 proto_tree_add_text(ospf_header_tree, tvb, 4, 4, "Source OSPF Router ID: %s",
296 ip_to_str(tvb_get_ptr(tvb, 4, 4)));
297 areaid=tvb_get_ntohl(tvb,8);
298 proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: %s%s",
299 ip_to_str(tvb_get_ptr(tvb, 8, 4)), areaid == 0 ? " (Backbone)" : "");
300 cksum = tvb_get_ntohs(tvb, 12);
301 length = tvb_length(tvb);
302 /* XXX - include only the length from the OSPF header? */
303 reported_length = tvb_reported_length(tvb);
305 /* No checksum supplied in the packet. */
306 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
307 "Packet Checksum: 0x%04x (none)", cksum);
308 } else if (!pinfo->fragmented && length >= reported_length
309 && length >= ospf_header_length
310 && (version == OSPF_VERSION_2 || version == OSPF_VERSION_3)) {
311 /* The packet isn't part of a fragmented datagram and isn't
312 truncated, and we know how to checksum this version of
313 OSPF, so we can checksum it. */
318 /* Header, not including the authentication data (the OSPFv2
319 checksum excludes the 64-bit authentication field). */
320 cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, 16);
321 cksum_vec[0].len = 16;
322 if (length > ospf_header_length) {
323 /* Rest of the packet, again not including the
324 authentication data. */
325 reported_length -= ospf_header_length;
326 cksum_vec[1].ptr = tvb_get_ptr(tvb, ospf_header_length, reported_length);
327 cksum_vec[1].len = reported_length;
330 /* There's nothing but a header. */
336 /* IPv6-style checksum, covering the entire OSPF packet
337 and a prepended IPv6 pseudo-header. */
339 /* Set up the fields of the pseudo-header. */
340 cksum_vec[0].ptr = pinfo->src.data;
341 cksum_vec[0].len = pinfo->src.len;
342 cksum_vec[1].ptr = pinfo->dst.data;
343 cksum_vec[1].len = pinfo->dst.len;
344 cksum_vec[2].ptr = (const guint8 *)&phdr;
345 phdr[0] = htonl(ospflen);
346 phdr[1] = htonl(IP_PROTO_OSPF);
347 cksum_vec[2].len = 8;
349 cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, reported_length);
350 cksum_vec[3].len = reported_length;
355 g_assert_not_reached();
358 computed_cksum = in_cksum(cksum_vec, cksum_vec_len);
359 if (computed_cksum == 0) {
360 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
361 "Packet Checksum: 0x%04x (correct)", cksum);
363 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
364 "Packet Checksum: 0x%04x (incorrect, should be 0x%04x)",
365 cksum, in_cksum_shouldbe(cksum, computed_cksum));
368 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
369 "Packet Checksum: 0x%04x", cksum);
373 /* Authentication is only valid for OSPFv2 */
374 if ( version == OSPF_VERSION_2 ) {
375 auth_type = tvb_get_ntohs(tvb, 14);
376 proto_tree_add_text(ospf_header_tree, tvb, 14, 2, "Auth Type: %s",
377 val_to_str(auth_type, auth_vals, "Unknown (%u)"));
381 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (none)");
384 case OSPF_AUTH_SIMPLE:
385 tvb_get_nstringz0(tvb, 16, 8, auth_data);
386 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data: %s", auth_data);
389 case OSPF_AUTH_CRYPT:
390 proto_tree_add_text(ospf_header_tree, tvb, 18, 1, "Auth Key ID: %u",
391 tvb_get_guint8(tvb, 18));
392 crypto_len = tvb_get_guint8(tvb, 19);
393 proto_tree_add_text(ospf_header_tree, tvb, 19, 1, "Auth Data Length: %u",
395 proto_tree_add_text(ospf_header_tree, tvb, 20, 4, "Auth Crypto Sequence Number: 0x%x",
396 tvb_get_ntohl(tvb, 20));
398 /* Show the message digest that was appended to the end of the
399 OSPF message - but only if it's present (we don't want
400 to get an exception before we've tried dissecting OSPF
402 if (tvb_bytes_exist(tvb, ospflen, crypto_len)) {
403 proto_tree_add_text(ospf_header_tree, tvb, ospflen, crypto_len,
405 tvb_bytes_to_str(tvb, ospflen, crypto_len));
410 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (unknown)");
416 /* Instance ID and "reserved" is OSPFv3-only */
417 if ( version == OSPF_VERSION_3 ) {
418 instance_ID = tvb_get_guint8(tvb, 14);
419 proto_tree_add_text(ospf_header_tree, tvb, 14, 1, "Instance ID: %u",
421 reserved = tvb_get_guint8(tvb, 15);
422 proto_tree_add_text(ospf_header_tree, tvb, 15, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
427 /* Adjust the length of the tvbuff to match the size of the OSPF
428 * packet (since the dissect routines use it to work out where the
429 * end of the OSPF packet is).
431 tvb_set_reported_length(tvb, ospflen);
433 switch (packet_type){
436 dissect_ospf_hello(tvb, ospf_header_length, ospf_tree, version);
440 dissect_ospf_db_desc(tvb, ospf_header_length, ospf_tree, version);
444 dissect_ospf_ls_req(tvb, ospf_header_length, ospf_tree, version);
448 dissect_ospf_ls_upd(tvb, ospf_header_length, ospf_tree, version);
452 dissect_ospf_ls_ack(tvb, ospf_header_length, ospf_tree, version);
456 call_dissector(data_handle,tvb_new_subset(tvb, ospf_header_length,-1,tvb_reported_length_remaining(tvb,ospf_header_length)), pinfo, tree);
463 dissect_ospf_hello(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
465 proto_tree *ospf_hello_tree;
468 ti = proto_tree_add_text(tree, tvb, offset,
469 tvb_length_remaining(tvb, offset),
470 "OSPF Hello Packet");
471 ospf_hello_tree = proto_item_add_subtree(ti, ett_ospf_hello);
475 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4, "Network Mask: %s",
476 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
477 proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 2,
478 "Hello Interval: %u seconds",
479 tvb_get_ntohs(tvb, offset + 4));
481 dissect_ospf_options(tvb, offset + 6, ospf_hello_tree, version);
482 proto_tree_add_text(ospf_hello_tree, tvb, offset + 7, 1, "Router Priority: %u",
483 tvb_get_guint8(tvb, offset + 7));
484 proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 4, "Router Dead Interval: %u seconds",
485 tvb_get_ntohl(tvb, offset + 8));
486 proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
487 ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
488 proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
489 ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
492 while (tvb_reported_length_remaining(tvb, offset) != 0) {
493 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
494 "Active Neighbor: %s",
495 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
500 proto_tree_add_text(ospf_hello_tree, tvb, offset + 0, 4, "Interface ID: %u",
501 tvb_get_ntohl(tvb, offset + 0));
502 proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 1, "Router Priority: %u",
503 tvb_get_guint8(tvb, offset + 4));
504 dissect_ospf_options(tvb, offset + 5, ospf_hello_tree, version);
505 proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 2,
506 "Hello Interval: %u seconds",
507 tvb_get_ntohs(tvb, offset + 8));
508 proto_tree_add_text(ospf_hello_tree, tvb, offset + 10, 2, "Router Dead Interval: %u seconds",
509 tvb_get_ntohs(tvb, offset + 10));
510 proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
511 ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
512 proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
513 ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
515 while (tvb_reported_length_remaining(tvb, offset) != 0) {
516 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
517 "Active Neighbor: %s",
518 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
530 dissect_ospf_db_desc(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
532 proto_tree *ospf_db_desc_tree=NULL;
536 char flags_string[20] = "";
539 ti = proto_tree_add_text(tree, tvb, offset,
540 tvb_length_remaining(tvb, offset),
541 "OSPF DB Description");
542 ospf_db_desc_tree = proto_item_add_subtree(ti, ett_ospf_desc);
548 proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 2, "Interface MTU: %u",
549 tvb_get_ntohs(tvb, offset));
551 dissect_ospf_options(tvb, offset + 2, ospf_db_desc_tree, version);
553 flags = tvb_get_guint8(tvb, offset + 3);
554 if (flags & OSPF_DBD_FLAG_MS)
555 strcat(flags_string, "MS");
556 if (flags & OSPF_DBD_FLAG_M) {
557 if (flags_string[0] != '\0')
558 strcat(flags_string, "/");
559 strcat(flags_string, "M");
561 if (flags & OSPF_DBD_FLAG_I) {
562 if (flags_string[0] != '\0')
563 strcat(flags_string, "/");
564 strcat(flags_string, "I");
566 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 3, 1, "Flags: 0x%x (%s)",
567 flags, flags_string);
568 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 4, "DD Sequence: %u",
569 tvb_get_ntohl(tvb, offset + 4));
576 reserved = tvb_get_guint8(tvb, offset);
577 proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
580 dissect_ospf_options(tvb, offset + 1, ospf_db_desc_tree, version);
582 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 2, "Interface MTU: %u",
583 tvb_get_ntohs(tvb, offset+4));
585 reserved = tvb_get_guint8(tvb, offset + 6);
586 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 6, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
589 flags = tvb_get_guint8(tvb, offset + 7);
590 if (flags & OSPF_DBD_FLAG_MS)
591 strcat(flags_string, "MS");
592 if (flags & OSPF_DBD_FLAG_M) {
593 if (flags_string[0] != '\0')
594 strcat(flags_string, "/");
595 strcat(flags_string, "M");
597 if (flags & OSPF_DBD_FLAG_I) {
598 if (flags_string[0] != '\0')
599 strcat(flags_string, "/");
600 strcat(flags_string, "I");
602 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 7, 1, "Flags: 0x%x (%s)",
603 flags, flags_string);
605 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 8, 4, "DD Sequence: %u",
606 tvb_get_ntohl(tvb, offset + 8));
616 /* LS Headers will be processed here */
617 /* skip to the end of DB-Desc header */
618 while (tvb_reported_length_remaining(tvb, offset) != 0) {
619 if ( version == OSPF_VERSION_2)
620 offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE);
622 if ( version == OSPF_VERSION_3)
623 offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE);
629 dissect_ospf_ls_req(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
631 proto_tree *ospf_lsr_tree;
636 /* zero or more LS requests may be within a LS Request */
637 /* we place every request for a LSA in a single subtree */
638 while (tvb_reported_length_remaining(tvb, offset) != 0) {
639 ti = proto_tree_add_text(tree, tvb, offset, OSPF_LS_REQ_LENGTH,
640 "Link State Request");
641 ospf_lsr_tree = proto_item_add_subtree(ti, ett_ospf_lsr);
643 reserved = tvb_get_guint8(tvb, offset);
644 proto_tree_add_text(ospf_lsr_tree, tvb, offset, 1,
645 (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
651 ls_type = tvb_get_ntohl(tvb, offset);
652 proto_tree_add_text(ospf_lsr_tree, tvb, offset, 4, "LS Type: %s (%u)",
653 val_to_str(ls_type, ls_type_vals, "Unknown"),
657 ls_type = tvb_get_ntohs(tvb, offset+2);
658 proto_tree_add_text(ospf_lsr_tree, tvb, offset+2, 2, "LS Type: %s (0x%04x)",
659 val_to_str(ls_type, v3_ls_type_vals, "Unknown"),
668 proto_tree_add_text(ospf_lsr_tree, tvb, offset + 4, 4, "Link State ID: %s",
669 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
670 proto_tree_add_text(ospf_lsr_tree, tvb, offset + 8, 4, "Advertising Router: %s",
671 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
678 dissect_ospf_ls_upd(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
680 proto_tree *ospf_lsa_upd_tree=NULL;
685 ti = proto_tree_add_text(tree, tvb, offset,
686 tvb_length_remaining(tvb, offset),
688 ospf_lsa_upd_tree = proto_item_add_subtree(ti, ett_ospf_lsa_upd);
690 lsa_nr = tvb_get_ntohl(tvb, offset);
691 proto_tree_add_text(ospf_lsa_upd_tree, tvb, offset, 4, "Number of LSAs: %u",
693 /* skip to the beginning of the first LSA */
694 offset += 4; /* the LS Upd Packet contains only a 32 bit #LSAs field */
697 while (lsa_counter < lsa_nr) {
698 if ( version == OSPF_VERSION_2)
699 offset = dissect_ospf_v2_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
701 if ( version == OSPF_VERSION_3)
702 offset = dissect_ospf_v3_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
708 dissect_ospf_ls_ack(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
710 /* the body of a LS Ack packet simply contains zero or more LSA Headers */
711 while (tvb_reported_length_remaining(tvb, offset) != 0) {
712 if ( version == OSPF_VERSION_2)
713 offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE);
715 if ( version == OSPF_VERSION_3)
716 offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE);
721 * Returns if an LSA is opaque, i.e. requires special treatment
724 is_opaque(int lsa_type)
726 return (lsa_type >= OSPF_LSTYPE_OP_LINKLOCAL &&
727 lsa_type <= OSPF_LSTYPE_OP_ASWIDE);
730 /* MPLS/TE TLV types */
731 #define MPLS_TLV_ROUTER 1
732 #define MPLS_TLV_LINK 2
734 /* MPLS/TE Link STLV types */
742 MPLS_LINK_MAX_RES_BW,
747 static const value_string mpls_link_stlv_str[] = {
748 {MPLS_LINK_TYPE, "Link Type"},
749 {MPLS_LINK_ID, "Link ID"},
750 {MPLS_LINK_LOCAL_IF, "Local Interface IP Address"},
751 {MPLS_LINK_REMOTE_IF, "Remote Interface IP Address"},
752 {MPLS_LINK_TE_METRIC, "Traffic Engineering Metric"},
753 {MPLS_LINK_MAX_BW, "Maximum Bandwidth"},
754 {MPLS_LINK_MAX_RES_BW, "Maximum Reservable Bandwidth"},
755 {MPLS_LINK_UNRES_BW, "Unreserved Bandwidth"},
756 {MPLS_LINK_COLOR, "Resource Class/Color"},
761 * Dissect MPLS/TE opaque LSA
764 dissect_ospf_lsa_mpls(tvbuff_t *tvb, int offset, proto_tree *tree,
768 proto_tree *mpls_tree;
769 proto_tree *tlv_tree;
770 proto_tree *stlv_tree;
776 int stlv_type, stlv_len, stlv_offset;
780 ti = proto_tree_add_text(tree, tvb, offset, length,
781 "MPLS Traffic Engineering LSA");
782 mpls_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls);
784 while (length != 0) {
785 tlv_type = tvb_get_ntohs(tvb, offset);
786 tlv_length = tvb_get_ntohs(tvb, offset + 2);
787 tlv_end_offset = offset + tlv_length + 4;
791 case MPLS_TLV_ROUTER:
792 ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
793 "Router Address: %s",
794 ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
795 tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_router);
796 proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 1 - Router Address");
797 proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
799 proto_tree_add_text(tlv_tree, tvb, offset+4, 4, "Router Address: %s",
800 ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
804 ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
806 tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
807 proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 2 - Link Information");
808 proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
810 stlv_offset = offset + 4;
812 /* Walk down the sub-TLVs for link information */
813 while (stlv_offset < tlv_end_offset) {
814 stlv_type = tvb_get_ntohs(tvb, stlv_offset);
815 stlv_len = tvb_get_ntohs(tvb, stlv_offset + 2);
816 stlv_name = val_to_str(stlv_type, mpls_link_stlv_str, "Unknown sub-TLV");
820 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
822 tvb_get_guint8(tvb, stlv_offset + 4));
823 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
824 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
825 "TLV Type: %u: %s", stlv_type, stlv_name);
826 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
828 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "%s: %u", stlv_name,
829 tvb_get_guint8(tvb, stlv_offset + 4));
833 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
834 "%s: %s (%x)", stlv_name,
835 ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)),
836 tvb_get_ntohl(tvb, stlv_offset + 4));
837 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
838 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
839 "TLV Type: %u: %s", stlv_type, stlv_name);
840 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
842 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %s (%x)", stlv_name,
843 ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)),
844 tvb_get_ntohl(tvb, stlv_offset + 4));
847 case MPLS_LINK_LOCAL_IF:
848 case MPLS_LINK_REMOTE_IF:
849 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
851 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
852 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
853 "TLV Type: %u: %s", stlv_type, stlv_name);
854 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
856 /* The Local/Remote Interface IP Address sub-TLV is TLV type 3/4, and is 4N
857 octets in length, where N is the number of neighbor addresses. */
858 for (i=0; i < stlv_len; i+=4)
859 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+i, 4, "%s: %s", stlv_name,
860 ip_to_str(tvb_get_ptr(tvb, stlv_offset+4+i, 4)));
863 case MPLS_LINK_TE_METRIC:
864 case MPLS_LINK_COLOR:
865 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
867 tvb_get_ntohl(tvb, stlv_offset + 4));
868 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
869 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
870 "TLV Type: %u: %s", stlv_type, stlv_name);
871 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
873 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %u", stlv_name,
874 tvb_get_ntohl(tvb, stlv_offset + 4));
877 case MPLS_LINK_MAX_BW:
878 case MPLS_LINK_MAX_RES_BW:
879 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
880 "%s: %ld", stlv_name,
881 tvb_ieee_to_long(tvb, stlv_offset + 4));
882 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
883 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
884 "TLV Type: %u: %s", stlv_type, stlv_name);
885 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
887 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %ld", stlv_name,
888 tvb_ieee_to_long(tvb, stlv_offset + 4));
891 case MPLS_LINK_UNRES_BW:
892 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
894 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
895 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
896 "TLV Type: %u: %s", stlv_type, stlv_name);
897 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
899 for (i = 0; i < 8; i++) {
900 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+(i*4), 4,
902 tvb_ieee_to_long(tvb, stlv_offset + 4 + i*4));
907 proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
908 "Unknown Link sub-TLV: %u", stlv_type);
911 stlv_offset += ((stlv_len+4+3)/4)*4;
916 ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
917 "Unknown LSA: %u", tlv_type);
918 tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
919 proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: %u - Unknown",
921 proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
923 proto_tree_add_text(tlv_tree, tvb, offset+4, tlv_length, "TLV Data");
927 offset += tlv_length + 4;
928 length -= tlv_length + 4;
933 * Dissect opaque LSAs
936 dissect_ospf_lsa_opaque(tvbuff_t *tvb, int offset, proto_tree *tree,
937 guint8 ls_id_type, guint32 length)
939 switch (ls_id_type) {
941 case OSPF_LSA_MPLS_TE:
942 dissect_ospf_lsa_mpls(tvb, offset, tree, length);
946 proto_tree_add_text(tree, tvb, offset, length,
947 "Unknown LSA Type %u", ls_id_type);
949 } /* switch on opaque LSA id */
953 dissect_ospf_v2_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
954 gboolean disassemble_body)
956 proto_tree *ospf_lsa_tree;
967 guint16 link_counter;
972 /* AS-external LSA */
978 ls_type = tvb_get_guint8(tvb, offset + 3);
979 ls_length = tvb_get_ntohs(tvb, offset + 18);
980 end_offset = offset + ls_length;
982 if (disassemble_body) {
983 ti = proto_tree_add_text(tree, tvb, offset, ls_length,
984 "%s (Type: %u)", val_to_str(ls_type, ls_type_vals,"Unkown"), ls_type);
986 ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
989 ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
991 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
992 tvb_get_ntohs(tvb, offset));
993 dissect_ospf_options(tvb, offset + 2, ospf_lsa_tree, OSPF_VERSION_2);
994 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 3, 1, "LSA Type: %u (%s)",
995 ls_type, val_to_str(ls_type,ls_type_vals,"Unknown"));
997 if (is_opaque(ls_type)) {
998 ls_id_type = tvb_get_guint8(tvb, offset + 4);
999 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 1, "Link State ID Opaque Type: %u",
1001 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3, "Link State ID Opaque ID: %u",
1002 tvb_get_ntoh24(tvb, offset + 5));
1005 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
1006 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
1009 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Advertising Router: %s",
1010 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
1011 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%04x",
1012 tvb_get_ntohl(tvb, offset + 12));
1013 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
1014 tvb_get_ntohs(tvb, offset + 16));
1016 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
1019 /* skip past the LSA header to the body */
1020 offset += OSPF_LSA_HEADER_LENGTH;
1021 ls_length -= OSPF_LSA_HEADER_LENGTH;
1023 if (!disassemble_body)
1028 case OSPF_LSTYPE_ROUTER:
1029 /* again: flags should be secified in detail */
1030 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x",
1031 tvb_get_guint8(tvb, offset));
1032 nr_links = tvb_get_ntohs(tvb, offset + 2);
1033 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "Number of Links: %u",
1036 /* nr_links links follow
1037 * maybe we should put each of the links into its own subtree ???
1039 for (link_counter = 1; link_counter <= nr_links; link_counter++) {
1040 /* check the Link Type and ID */
1041 link_type = tvb_get_guint8(tvb, offset + 8);
1042 switch (link_type) {
1045 link_type_str="Point-to-point connection to another router";
1046 link_id="Neighboring router's Router ID";
1049 case OSPF_LINK_TRANSIT:
1050 link_type_str="Connection to a transit network";
1051 link_id="IP address of Designated Router";
1054 case OSPF_LINK_STUB:
1055 link_type_str="Connection to a stub network";
1056 link_id="IP network/subnet number";
1059 case OSPF_LINK_VIRTUAL:
1060 link_type_str="Virtual link";
1061 link_id="Neighboring router's Router ID";
1065 link_type_str="Unknown link type";
1066 link_id="Unknown link ID";
1070 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "%s: %s", link_id,
1071 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1073 /* link_data should be specified in detail (e.g. network mask) (depends on link type)*/
1074 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link Data: %s",
1075 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
1077 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 1, "Link Type: %u - %s",
1078 link_type, link_type_str);
1079 nr_tos = tvb_get_guint8(tvb, offset + 9);
1080 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 9, 1, "Number of TOS metrics: %u",
1082 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 10, 2, "TOS 0 metric: %u",
1083 tvb_get_ntohs(tvb, offset + 10));
1087 /* nr_tos metrics may follow each link
1088 * ATTENTION: TOS metrics are not tested (I don't have TOS
1090 * please send me a mail if it is/isn't working
1092 for (tos_counter = 1; tos_counter <= nr_tos; tos_counter++) {
1093 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
1094 tvb_get_guint8(tvb, offset),
1095 tvb_get_ntohs(tvb, offset + 2));
1101 case OSPF_LSTYPE_NETWORK:
1102 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
1103 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1106 while (offset < end_offset) {
1107 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
1108 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1113 case OSPF_LSTYPE_SUMMERY:
1114 /* Type 3 and 4 LSAs have the same format */
1115 case OSPF_LSTYPE_ASBR:
1116 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
1117 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1120 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Metric: %u",
1121 tvb_get_ntoh24(tvb, offset + 1));
1124 /* TOS-specific information, if any */
1125 while (offset < end_offset) {
1126 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
1127 tvb_get_guint8(tvb, offset),
1128 tvb_get_ntoh24(tvb, offset + 1));
1133 case OSPF_LSTYPE_ASEXT:
1134 case OSPF_LSTYPE_ASEXT7:
1135 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
1136 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1139 options = tvb_get_guint8(tvb, offset);
1140 if (options & 0x80) { /* check wether or not E bit is set */
1141 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1142 "External Type: Type 2 (metric is larger than any other link state path)");
1144 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1145 "External Type: Type 1 (metric is specified in the same units as interface cost)");
1147 /* the metric field of a AS-external LAS is specified in 3 bytes */
1148 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3, "Metric: %u",
1149 tvb_get_ntoh24(tvb, offset + 1));
1152 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
1153 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1156 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
1157 tvb_get_ntohl(tvb, offset));
1160 /* TOS-specific information, if any */
1161 while (offset < end_offset) {
1162 options = tvb_get_guint8(tvb, offset);
1163 if (options & 0x80) { /* check wether or not E bit is set */
1164 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1165 "External Type: Type 2 (metric is larger than any other link state path)");
1167 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1168 "External Type: Type 1 (metric is specified in the same units as interface cost)");
1170 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
1172 tvb_get_ntoh24(tvb, offset + 1));
1175 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
1176 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1179 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
1180 tvb_get_ntohl(tvb, offset));
1185 case OSPF_LSTYPE_OP_LINKLOCAL:
1186 case OSPF_LSTYPE_OP_AREALOCAL:
1187 case OSPF_LSTYPE_OP_ASWIDE:
1188 dissect_ospf_lsa_opaque(tvb, offset, ospf_lsa_tree, ls_id_type,
1190 offset += ls_length;
1194 /* unknown LSA type */
1195 proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
1196 "Unknown LSA Type");
1197 offset += ls_length;
1200 /* return the offset of the next LSA */
1205 dissect_ospf_v3_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
1206 gboolean disassemble_body)
1208 proto_tree *ospf_lsa_tree;
1218 char *link_type_str;
1221 guint8 router_lsa_flags;
1222 char router_lsa_flags_string[5];
1224 guint8 router_priority;
1225 guint32 number_prefixes;
1226 guint8 prefix_length;
1229 guint16 referenced_ls_type;
1232 guint8 flags_string[4];
1233 guint32 external_route_tag;
1236 ls_type = tvb_get_ntohs(tvb, offset + 2);
1237 ls_length = tvb_get_ntohs(tvb, offset + 18);
1238 end_offset = offset + ls_length;
1240 if (disassemble_body) {
1241 ti = proto_tree_add_text(tree, tvb, offset, ls_length,
1242 "%s (Type: 0x%04x)", val_to_str(ls_type, v3_ls_type_vals,"Unknown"), ls_type);
1244 ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
1247 ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
1249 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
1250 tvb_get_ntohs(tvb, offset));
1252 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "LSA Type: 0x%04x (%s)",
1253 ls_type, val_to_str(ls_type, v3_ls_type_vals,"Unkown"));
1255 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
1256 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
1258 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Advertising Router: %s",
1259 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
1260 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: %d",
1261 tvb_get_ntohl(tvb, offset + 12));
1262 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
1263 tvb_get_ntohs(tvb, offset + 16));
1265 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
1268 /* skip past the LSA header to the body */
1269 offset += OSPF_LSA_HEADER_LENGTH;
1270 ls_length -= OSPF_LSA_HEADER_LENGTH;
1272 if (!disassemble_body)
1278 case OSPF_V3_LSTYPE_ROUTER:
1280 /* flags field in an router-lsa */
1281 router_lsa_flags=tvb_get_guint8(tvb,offset);
1282 if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_B)
1283 router_lsa_flags_string[3] = 'B';
1285 router_lsa_flags_string[3] = '.';
1286 if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_E)
1287 router_lsa_flags_string[2] = 'E';
1289 router_lsa_flags_string[2] = '.';
1290 if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_V)
1291 router_lsa_flags_string[1] = 'V';
1293 router_lsa_flags_string[1] = '.';
1294 if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_W)
1295 router_lsa_flags_string[0] = 'W';
1297 router_lsa_flags_string[0] = '.';
1299 router_lsa_flags_string[4]=0;
1301 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x (%s)",
1302 router_lsa_flags, router_lsa_flags_string);
1304 /* options field in an router-lsa */
1305 dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
1307 /* skip the router-lsa flags and options */
1312 proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
1313 "Router Interfaces:");
1315 /* scan all router-lsa router interfaces */
1316 /* maybe we should put each of the links into its own subtree ??? */
1317 while (ls_length > 0 ) {
1319 /* check the type */
1320 link_type = tvb_get_guint8(tvb, offset);
1321 switch (link_type) {
1323 case OSPF_V3_LINK_PTP:
1324 link_type_str="Point-to-point connection to another router";
1327 case OSPF_V3_LINK_TRANSIT:
1328 link_type_str="Connection to a transit network";
1331 case OSPF_V3_LINK_RESERVED:
1332 link_type_str="Connection to a stub network";
1335 case OSPF_V3_LINK_VIRTUAL:
1336 link_type_str="Virtual link";
1340 link_type_str="Unknown link type";
1344 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Type: %u (%s)", link_type,link_type_str);
1346 /* reserved field */
1347 reserved = tvb_get_guint8(tvb, offset+1);
1348 proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 1,
1349 (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
1352 metric=tvb_get_ntohs(tvb, offset+2);
1353 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2,"Metric: %u",metric);
1356 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Interface ID: %u",
1357 tvb_get_ntohl(tvb, offset + 4));
1359 /* Neighbor Interface ID */
1360 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Neighbor Interface ID: %u",
1361 tvb_get_ntohl(tvb, offset + 8));
1363 /* Neighbor Router ID */
1364 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "Neighbor Router ID: %s",
1365 ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
1367 /* skip to the (possible) next entry */
1374 case OSPF_V3_LSTYPE_NETWORK:
1376 /* reserved field */
1377 reserved = tvb_get_guint8(tvb, offset);
1378 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1379 (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
1381 /* options field in an network-lsa */
1382 dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
1387 while (ls_length > 0 ) {
1388 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
1389 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1396 case OSPF_V3_LSTYPE_INTER_AREA_PREFIX:
1398 /* reserved field */
1399 reserved = tvb_get_guint8(tvb, offset);
1400 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1401 (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
1404 metric=tvb_get_ntoh24(tvb, offset+11);
1405 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3,"Metric: %u",metric);
1408 prefix_length=tvb_get_guint8(tvb, offset+4);
1409 proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length);
1411 /* prefix options */
1412 dissect_ospf_v3_prefix_options(tvb, offset+5, ospf_lsa_tree);
1414 /* 16 bits reserved */
1415 reserved16=tvb_get_ntohs(tvb, offset+6);
1416 proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,
1417 (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved16);
1421 /* address_prefix */
1422 dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
1424 offset+=(prefix_length+31)/32*4;
1429 case OSPF_V3_LSTYPE_INTER_AREA_ROUTER:
1431 /* reserved field */
1432 reserved = tvb_get_guint8(tvb, offset);
1433 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
1434 (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
1436 /* options field in an inter-area-router-lsa */
1437 dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
1439 /* reserved field */
1440 reserved = tvb_get_guint8(tvb, offset+4);
1441 proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1,
1442 (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
1445 metric=tvb_get_ntoh24(tvb, offset+6);
1446 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 6, 3,"Metric: %u",metric);
1448 /* Destination Router ID */
1449 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Destination Router ID: %s",
1450 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
1456 case OSPF_V3_LSTYPE_AS_EXTERNAL:
1459 flags=tvb_get_guint8(tvb, offset);
1460 if (flags & OSPF_V3_AS_EXTERNAL_FLAG_E)
1461 flags_string[0] = 'E';
1463 flags_string[0] = '.';
1464 if (flags & OSPF_V3_AS_EXTERNAL_FLAG_F)
1465 flags_string[1] = 'F';
1467 flags_string[1] = '.';
1468 if (flags & OSPF_V3_AS_EXTERNAL_FLAG_T)
1469 flags_string[2] = 'T';
1471 flags_string[2] = '.';
1475 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x (%s)",
1476 flags, flags_string);
1478 /* 24 bits metric */
1479 metric=tvb_get_ntoh24(tvb, offset+1);
1480 proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 3,
1481 "Metric: %u", metric);
1484 prefix_length=tvb_get_guint8(tvb, offset+4);
1485 proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length);
1487 /* prefix options */
1488 dissect_ospf_v3_prefix_options(tvb, offset+5, ospf_lsa_tree);
1490 /* referenced LS type */
1491 referenced_ls_type=tvb_get_ntohs(tvb, offset+6);
1492 proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,"Referenced LS type 0x%04x (%s)",
1493 referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
1497 /* address_prefix */
1498 dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
1500 offset+=(prefix_length+31)/32*4;
1502 /* Forwarding Address (optional - only if F-flag is on) */
1503 if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_F) ) {
1504 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 16,"Forwarding Address: %s",
1505 ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16)));
1510 /* External Route Tag (optional - only if T-flag is on) */
1511 if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_T) ) {
1512 external_route_tag=tvb_get_ntohl(tvb, offset);
1513 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4,"External Route Tag: 0x%04x",
1514 external_route_tag);
1519 /* Referenced Link State ID (optional - only if Referenced LS type is non-zero */
1520 if ( (offset < end_offset) && (referenced_ls_type != 0) ) {
1521 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Referenced Link State ID: %s",
1522 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1528 case OSPF_V3_LSTYPE_LINK:
1530 /* router priority */
1531 router_priority=tvb_get_guint8(tvb, offset);
1532 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Router Priority: %u", router_priority);
1534 /* options field in an link-lsa */
1535 dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
1537 /* Link-local Interface Address */
1538 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 16, "Link-local Interface Address: %s",
1539 ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset + 4, 16)));
1541 /* Number prefixes */
1542 number_prefixes=tvb_get_ntohl(tvb, offset + 20);
1543 proto_tree_add_text(ospf_lsa_tree, tvb, offset+20, 4, "# prefixes: %d",number_prefixes);
1547 while (number_prefixes > 0) {
1550 prefix_length=tvb_get_guint8(tvb, offset);
1551 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length);
1553 /* prefix options */
1554 dissect_ospf_v3_prefix_options(tvb, offset+1, ospf_lsa_tree);
1556 /* 16 bits reserved */
1557 reserved16=tvb_get_ntohs(tvb, offset+2);
1558 proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,
1559 (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved16);
1563 /* address_prefix */
1564 dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
1566 offset+=(prefix_length+31)/32*4;
1573 case OSPF_V3_LSTYPE_INTRA_AREA_PREFIX:
1576 number_prefixes=tvb_get_ntohs(tvb, offset);
1577 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2,"# prefixes: %u",number_prefixes);
1579 /* referenced LS type */
1580 referenced_ls_type=tvb_get_ntohs(tvb, offset+2);
1581 proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,"Referenced LS type 0x%04x (%s)",
1582 referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
1584 /* Referenced Link State ID */
1585 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Referenced Link State ID: %s",
1586 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
1588 /* Referenced Advertising Router */
1589 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Referenced Advertising Router: %s",
1590 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
1594 while (number_prefixes > 0) {
1597 prefix_length=tvb_get_guint8(tvb, offset);
1598 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length);
1600 /* prefix options */
1601 dissect_ospf_v3_prefix_options(tvb, offset+1, ospf_lsa_tree);
1603 /* 16 bits metric */
1604 metric=tvb_get_ntohs(tvb, offset+2);
1605 proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,
1606 "Metric: %u", metric);
1610 /* address_prefix */
1611 dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
1613 offset+=(prefix_length+31)/32*4;
1620 /* unknown LSA type */
1621 proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
1622 "Unknown LSA Type 0x%04x",ls_type);
1623 offset += ls_length;
1626 /* return the offset of the next LSA */
1632 dissect_ospf_options(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
1634 guint8 options_ospfv2;
1635 guint32 options_ospfv3;
1636 char options_string[20] = "";
1638 /* ATTENTION !!! no check for length of options string - with OSPFv3 maximum length is 14 characters */
1640 switch ( version ) {
1642 case OSPF_VERSION_2:
1644 options_ospfv2 = tvb_get_guint8(tvb, offset);
1646 if (options_ospfv2 & OSPF_V2_OPTIONS_E)
1647 strcat(options_string, "E");
1649 if (options_ospfv2 & OSPF_V2_OPTIONS_MC) {
1650 if (options_string[0] != '\0')
1651 strcat(options_string, "/");
1652 strcat(options_string, "MC");
1655 if (options_ospfv2 & OSPF_V2_OPTIONS_NP) {
1656 if (options_string[0] != '\0')
1657 strcat(options_string, "/");
1658 strcat(options_string, "NP");
1661 if (options_ospfv2 & OSPF_V2_OPTIONS_EA) {
1662 if (options_string[0] != '\0')
1663 strcat(options_string, "/");
1664 strcat(options_string, "EA");
1667 if (options_ospfv2 & OSPF_V2_OPTIONS_DC) {
1668 if (options_string[0] != '\0')
1669 strcat(options_string, "/");
1670 strcat(options_string, "DC");
1673 if (options_ospfv2 & OSPF_V2_OPTIONS_O) {
1674 if (options_string[0] != '\0')
1675 strcat(options_string, "/");
1676 strcat(options_string, "O");
1679 if (options_ospfv2 & OSPF_V2_OPTIONS_DN) {
1680 if (options_string[0] != '\0')
1681 strcat(options_string, "/");
1682 strcat(options_string, "DN");
1685 proto_tree_add_text(tree, tvb, offset, 1, "Options: 0x%x (%s)",
1686 options_ospfv2, options_string);
1690 case OSPF_VERSION_3:
1692 options_ospfv3 = tvb_get_ntoh24(tvb, offset);
1694 if (options_ospfv3 & OSPF_V3_OPTIONS_V6)
1695 strcat(options_string, "V6");
1697 if (options_ospfv3 & OSPF_V3_OPTIONS_E)
1698 if (options_string[0] != '\0')
1699 strcat(options_string, "/");
1700 strcat(options_string, "E");
1702 if (options_ospfv3 & OSPF_V3_OPTIONS_MC) {
1703 if (options_string[0] != '\0')
1704 strcat(options_string, "/");
1705 strcat(options_string, "MC");
1708 if (options_ospfv3 & OSPF_V3_OPTIONS_N) {
1709 if (options_string[0] != '\0')
1710 strcat(options_string, "/");
1711 strcat(options_string, "N");
1714 if (options_ospfv3 & OSPF_V3_OPTIONS_R) {
1715 if (options_string[0] != '\0')
1716 strcat(options_string, "/");
1717 strcat(options_string, "R");
1720 if (options_ospfv3 & OSPF_V3_OPTIONS_DC) {
1721 if (options_string[0] != '\0')
1722 strcat(options_string, "/");
1723 strcat(options_string, "DC");
1726 proto_tree_add_text(tree, tvb, offset, 3, "Options: 0x%x (%s)",
1727 options_ospfv3, options_string);
1737 static void dissect_ospf_v3_prefix_options(tvbuff_t *tvb, int offset, proto_tree *tree)
1740 guint8 prefix_options;
1741 char prefix_options_string[11];
1746 prefix_options=tvb_get_guint8(tvb, offset);
1748 strcpy(prefix_options_string,"");
1750 if (prefix_options & OSPF_V3_PREFIX_OPTION_P) {
1751 strcat(prefix_options_string, "P");
1755 if (prefix_options & OSPF_V3_PREFIX_OPTION_MC) {
1756 if ( (position > 0) && (prefix_options_string[position-1] != '/') ) {
1757 strcat(prefix_options_string, "/");
1760 strcat(prefix_options_string, "MC");
1764 if (prefix_options & OSPF_V3_PREFIX_OPTION_LA) {
1765 if ( (position > 0) && (prefix_options_string[position-1] != '/') ) {
1766 strcat(prefix_options_string, "/");
1769 strcat(prefix_options_string, "LA");
1773 if (prefix_options & OSPF_V3_PREFIX_OPTION_NU) {
1774 if ( (position > 0) && (prefix_options_string[position-1] != '/') ) {
1775 strcat(prefix_options_string, "/");
1778 strcat(prefix_options_string, "NU");
1781 prefix_options_string[10]=0;
1783 proto_tree_add_text(tree, tvb, offset, 1, "PrefixOptions: 0x%02x (%s)",prefix_options, prefix_options_string);
1788 static void dissect_ospf_v3_address_prefix(tvbuff_t *tvb, int offset, int prefix_length, proto_tree *tree)
1796 guint8 bytes_to_process;
1799 start_offset=offset;
1802 bytes_to_process=((prefix_length+31)/32)*4;
1804 while (bytes_to_process > 0 ) {
1806 value=tvb_get_guint8(tvb, offset);
1808 if ( (position > 0) && ( (position%2) == 0 ) )
1809 buffer[bufpos++]=':';
1811 sprintf(bytebuf,"%02x",value);
1812 buffer[bufpos++]=bytebuf[0];
1813 buffer[bufpos++]=bytebuf[1];
1821 proto_tree_add_text(tree, tvb, start_offset, ((prefix_length+31)/32)*4, "Address Prefix: %s",buffer);
1827 proto_register_ospf(void)
1829 /* static hf_register_info hf[] = {
1831 { "Name", "ospf.abbreviation", TYPE, VALS_POINTER }},
1833 static gint *ett[] = {
1842 &ett_ospf_lsa_mpls_router,
1843 &ett_ospf_lsa_mpls_link,
1844 &ett_ospf_lsa_mpls_link_stlv
1847 proto_ospf = proto_register_protocol("Open Shortest Path First",
1849 /* proto_register_field_array(proto_ospf, hf, array_length(hf));*/
1850 proto_register_subtree_array(ett, array_length(ett));
1854 proto_reg_handoff_ospf(void)
1856 dissector_handle_t ospf_handle;
1858 ospf_handle = create_dissector_handle(dissect_ospf, proto_ospf);
1859 dissector_add("ip.proto", IP_PROTO_OSPF, ospf_handle);
1860 data_handle = find_dissector("data");