2 * Routines for OSPF packet disassembly
3 * (c) Copyright Hannes R. Boehm <hannes@boehm.org>
5 * $Id: packet-ospf.c,v 1.34 2001/01/03 16:41:07 gram 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.
12 * TOS - support is not fully implemented
14 * Ethereal - Network traffic analyzer
15 * By Gerald Combs <gerald@zing.org>
16 * Copyright 1998 Gerald Combs
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #ifdef HAVE_SYS_TYPES_H
39 # include <sys/types.h>
42 #ifdef HAVE_NETINET_IN_H
43 # include <netinet/in.h>
51 #include "packet-ip.h"
53 #include "ieee-float.h"
55 #define OSPF_HEADER_LENGTH 24
58 #define OSPF_DB_DESC 2
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" },
72 #define OSPF_AUTH_NONE 0
73 #define OSPF_AUTH_SIMPLE 1
74 #define OSPF_AUTH_CRYPT 2
76 static const value_string auth_vals[] = {
77 {OSPF_AUTH_NONE, "Null" },
78 {OSPF_AUTH_SIMPLE, "Simple password" },
79 {OSPF_AUTH_CRYPT, "Cryptographic" },
83 #define OSPF_OPTIONS_E 0x02
84 #define OSPF_OPTIONS_MC 0x04
85 #define OSPF_OPTIONS_NP 0x08
86 #define OSPF_OPTIONS_EA 0x10
87 #define OSPF_OPTIONS_DC 0x20
89 #define OSPF_DBD_FLAG_MS 1
90 #define OSPF_DBD_FLAG_M 2
91 #define OSPF_DBD_FLAG_I 4
93 #define OSPF_LS_REQ_LENGTH 12
95 #define OSPF_LSTYPE_ROUTER 1
96 #define OSPF_LSTYPE_NETWORK 2
97 #define OSPF_LSTYPE_SUMMERY 3
98 #define OSPF_LSTYPE_ASBR 4
99 #define OSPF_LSTYPE_ASEXT 5
100 #define OSPF_LSTYPE_ASEXT7 7
102 /* Opaque LSA types */
103 #define OSPF_LSTYPE_OP_LINKLOCAL 9
104 #define OSPF_LSTYPE_OP_AREALOCAL 10
105 #define OSPF_LSTYPE_OP_ASWIDE 11
107 #define OSPF_LINK_PTP 1
108 #define OSPF_LINK_TRANSIT 2
109 #define OSPF_LINK_STUB 3
110 #define OSPF_LINK_VIRTUAL 4
112 #define OSPF_LSA_HEADER_LENGTH 20
114 /* Known opaque LSAs */
115 #define OSPF_LSA_MPLS_TE 1
117 static const value_string ls_type_vals[] = {
118 {OSPF_LSTYPE_ROUTER, "Router-LSA" },
119 {OSPF_LSTYPE_NETWORK, "Network-LSA" },
120 {OSPF_LSTYPE_SUMMERY, "Summary-LSA (IP network)" },
121 {OSPF_LSTYPE_ASBR, "Summary-LSA (ASBR)" },
122 {OSPF_LSTYPE_ASEXT, "AS-External-LSA (ASBR)" },
126 static int proto_ospf = -1;
128 static gint ett_ospf = -1;
129 static gint ett_ospf_hdr = -1;
130 static gint ett_ospf_hello = -1;
131 static gint ett_ospf_desc = -1;
132 static gint ett_ospf_lsr = -1;
133 static gint ett_ospf_lsa = -1;
134 static gint ett_ospf_lsa_upd = -1;
136 /* Trees for opaque LSAs */
137 static gint ett_ospf_lsa_mpls = -1;
138 static gint ett_ospf_lsa_mpls_router = -1;
139 static gint ett_ospf_lsa_mpls_link = -1;
140 static gint ett_ospf_lsa_mpls_link_stlv = -1;
142 static void dissect_ospf_hello(tvbuff_t*, int, proto_tree*);
143 static void dissect_ospf_db_desc(tvbuff_t*, int, proto_tree*);
144 static void dissect_ospf_ls_req(tvbuff_t*, int, proto_tree*);
145 static void dissect_ospf_ls_upd(tvbuff_t*, int, proto_tree*);
146 static void dissect_ospf_ls_ack(tvbuff_t*, int, proto_tree*);
148 /* dissect_ospf_lsa returns the offset of the next LSA
149 * if disassemble_body is set to FALSE (e.g. in LSA ACK
150 * packets), the offset is set to the offset of the next
153 static int dissect_ospf_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body);
155 static void dissect_ospf_options(tvbuff_t *, int, proto_tree *);
158 dissect_ospf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
160 proto_tree *ospf_tree = NULL;
162 proto_tree *ospf_header_tree;
168 guint16 cksum, computed_cksum;
169 guint length, reported_length;
174 CHECK_DISPLAY_AS_DATA(proto_ospf, tvb, pinfo, tree);
176 pinfo->current_proto = "OSPF";
178 version = tvb_get_guint8(tvb, 0);
179 packet_type = tvb_get_guint8(tvb, 1);
180 if (check_col(pinfo->fd, COL_PROTOCOL))
181 col_set_str(pinfo->fd, COL_PROTOCOL, "OSPF");
182 if (check_col(pinfo->fd, COL_INFO)) {
183 col_add_str(pinfo->fd, COL_INFO,
184 val_to_str(packet_type, pt_vals, "Unknown (%u)"));
188 ospflen = tvb_get_ntohs(tvb, 2);
190 ti = proto_tree_add_item(tree, proto_ospf, tvb, 0, ospflen, FALSE);
191 ospf_tree = proto_item_add_subtree(ti, ett_ospf);
193 ti = proto_tree_add_text(ospf_tree, tvb, 0, OSPF_HEADER_LENGTH,
195 ospf_header_tree = proto_item_add_subtree(ti, ett_ospf_hdr);
197 proto_tree_add_text(ospf_header_tree, tvb, 0, 1, "OSPF Version: %u",
199 proto_tree_add_text(ospf_header_tree, tvb, 1, 1, "OSPF Packet Type: %u (%s)",
201 val_to_str(packet_type, pt_vals, "Unknown"));
202 proto_tree_add_text(ospf_header_tree, tvb, 2, 2, "Packet Length: %u",
204 proto_tree_add_text(ospf_header_tree, tvb, 4, 4, "Source OSPF Router ID: %s",
205 ip_to_str(tvb_get_ptr(tvb, 4, 4)));
206 if (tvb_get_ntohl(tvb, 8) == 0) {
207 proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: Backbone");
209 proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: %s",
210 ip_to_str(tvb_get_ptr(tvb, 8, 4)));
212 cksum = tvb_get_ntohs(tvb, 12);
213 length = tvb_length(tvb);
214 /* XXX - include only the length from the OSPF header? */
215 reported_length = tvb_reported_length(tvb);
216 if (!pi.fragmented && length >= reported_length
217 && length >= OSPF_HEADER_LENGTH) {
218 /* The packet isn't part of a fragmented datagram and isn't
219 truncated, so we can checksum it. */
221 /* Header, not including the authentication data (the OSPF
222 checksum excludes the 64-bit authentication field). */
223 cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, 16);
224 cksum_vec[0].len = 16;
225 if (length > OSPF_HEADER_LENGTH) {
226 /* Rest of the packet, again not including the
227 authentication data. */
228 reported_length -= OSPF_HEADER_LENGTH;
229 cksum_vec[1].ptr = tvb_get_ptr(tvb, OSPF_HEADER_LENGTH, reported_length);
230 cksum_vec[1].len = reported_length;
233 /* There's nothing but a header. */
236 computed_cksum = in_cksum(cksum_vec, cksum_vec_len);
237 if (computed_cksum == 0) {
238 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
239 "Packet Checksum: 0x%04x (correct)", cksum);
241 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
242 "Packet Checksum: 0x%04x (incorrect, should be 0x%04x)",
243 cksum, in_cksum_shouldbe(cksum, computed_cksum));
246 proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
247 "Packet Checksum: 0x%04x", cksum);
249 auth_type = tvb_get_ntohs(tvb, 14);
250 proto_tree_add_text(ospf_header_tree, tvb, 14, 2, "Auth Type: %s",
251 val_to_str(auth_type, auth_vals, "Unknown (%u)"));
255 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (none)");
258 case OSPF_AUTH_SIMPLE:
259 tvb_get_nstringz0(tvb, 16, 8, auth_data);
260 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data: %s", auth_data);
263 case OSPF_AUTH_CRYPT:
264 proto_tree_add_text(ospf_header_tree, tvb, 18, 1, "Auth Key ID: %u",
265 tvb_get_guint8(tvb, 18));
266 crypto_len = tvb_get_guint8(tvb, 19);
267 proto_tree_add_text(ospf_header_tree, tvb, 19, 1, "Auth Data Length: %u",
269 proto_tree_add_text(ospf_header_tree, tvb, 20, 4, "Auth Crypto Sequence Number: 0x%x",
270 tvb_get_ntohl(tvb, 20));
272 /* Show the message digest that was appended to the end of the
273 OSPF message - but only if it's present (we don't want
274 to get an exception before we've tried dissecting OSPF
276 if (tvb_bytes_exist(tvb, ospflen, crypto_len)) {
277 proto_tree_add_text(ospf_header_tree, tvb, ospflen, crypto_len,
279 tvb_bytes_to_str(tvb, ospflen, crypto_len));
284 proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (unknown)");
288 /* Adjust the length of the tvbuff to match the size of the OSPF
289 * packet (since the dissect routines use it to work out where the
290 * end of the OSPF packet is).
292 tvb_set_reported_length(tvb, ospflen);
294 switch (packet_type){
297 dissect_ospf_hello(tvb, OSPF_HEADER_LENGTH, ospf_tree);
301 dissect_ospf_db_desc(tvb, OSPF_HEADER_LENGTH, ospf_tree);
305 dissect_ospf_ls_req(tvb, OSPF_HEADER_LENGTH, ospf_tree);
309 dissect_ospf_ls_upd(tvb, OSPF_HEADER_LENGTH, ospf_tree);
313 dissect_ospf_ls_ack(tvb, OSPF_HEADER_LENGTH, ospf_tree);
317 dissect_data(tvb, OSPF_HEADER_LENGTH, pinfo, tree);
324 dissect_ospf_hello(tvbuff_t *tvb, int offset, proto_tree *tree)
326 proto_tree *ospf_hello_tree;
329 ti = proto_tree_add_text(tree, tvb, offset,
330 tvb_length_remaining(tvb, offset),
331 "OSPF Hello Packet");
332 ospf_hello_tree = proto_item_add_subtree(ti, ett_ospf_hello);
334 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4, "Network Mask: %s",
335 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
336 proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 2,
337 "Hello Interval: %u seconds",
338 tvb_get_ntohs(tvb, offset + 4));
340 dissect_ospf_options(tvb, offset + 6, ospf_hello_tree);
341 proto_tree_add_text(ospf_hello_tree, tvb, offset + 7, 1, "Router Priority: %u",
342 tvb_get_guint8(tvb, offset + 7));
343 proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 4, "Router Dead Interval: %u seconds",
344 tvb_get_ntohl(tvb, offset + 8));
345 proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
346 ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
347 proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
348 ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
351 while (tvb_reported_length_remaining(tvb, offset) != 0) {
352 proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
353 "Active Neighbor: %s",
354 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
360 dissect_ospf_db_desc(tvbuff_t *tvb, int offset, proto_tree *tree)
362 proto_tree *ospf_db_desc_tree=NULL;
365 char flags_string[20] = "";
368 ti = proto_tree_add_text(tree, tvb, offset,
369 tvb_length_remaining(tvb, offset),
370 "OSPF DB Description");
371 ospf_db_desc_tree = proto_item_add_subtree(ti, ett_ospf_desc);
373 proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 2, "Interface MTU: %u",
374 tvb_get_ntohs(tvb, offset));
376 dissect_ospf_options(tvb, offset + 2, ospf_db_desc_tree);
378 flags = tvb_get_guint8(tvb, offset + 3);
379 if (flags & OSPF_DBD_FLAG_MS)
380 strcat(flags_string, "MS");
381 if (flags & OSPF_DBD_FLAG_M) {
382 if (flags_string[0] != '\0')
383 strcat(flags_string, "/");
384 strcat(flags_string, "M");
386 if (flags & OSPF_DBD_FLAG_I) {
387 if (flags_string[0] != '\0')
388 strcat(flags_string, "/");
389 strcat(flags_string, "I");
391 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 3, 1, "Flags: 0x%x (%s)",
392 flags, flags_string);
393 proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 4, "DD Sequence: %u",
394 tvb_get_ntohl(tvb, offset + 4));
397 /* LS Headers will be processed here */
398 /* skip to the end of DB-Desc header */
400 while (tvb_reported_length_remaining(tvb, offset) != 0)
401 offset = dissect_ospf_lsa(tvb, offset, tree, FALSE);
405 dissect_ospf_ls_req(tvbuff_t *tvb, int offset, proto_tree *tree)
407 proto_tree *ospf_lsr_tree;
411 /* zero or more LS requests may be within a LS Request */
412 /* we place every request for a LSA in a single subtree */
413 while (tvb_reported_length_remaining(tvb, offset) != 0) {
414 ti = proto_tree_add_text(tree, tvb, offset, OSPF_LS_REQ_LENGTH,
415 "Link State Request");
416 ospf_lsr_tree = proto_item_add_subtree(ti, ett_ospf_lsr);
418 ls_type = tvb_get_ntohl(tvb, offset);
419 proto_tree_add_text(ospf_lsr_tree, tvb, offset, 4, "LS Type: %s (%u)",
420 val_to_str(ls_type, ls_type_vals, "Unknown"),
423 proto_tree_add_text(ospf_lsr_tree, tvb, offset + 4, 4, "Link State ID: %s",
424 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
425 proto_tree_add_text(ospf_lsr_tree, tvb, offset + 8, 4, "Advertising Router: %s",
426 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
433 dissect_ospf_ls_upd(tvbuff_t *tvb, int offset, proto_tree *tree)
435 proto_tree *ospf_lsa_upd_tree=NULL;
440 ti = proto_tree_add_text(tree, tvb, offset,
441 tvb_length_remaining(tvb, offset),
443 ospf_lsa_upd_tree = proto_item_add_subtree(ti, ett_ospf_lsa_upd);
445 lsa_nr = tvb_get_ntohl(tvb, offset);
446 proto_tree_add_text(ospf_lsa_upd_tree, tvb, offset, 4, "Number of LSAs: %u",
448 /* skip to the beginning of the first LSA */
449 offset += 4; /* the LS Upd Packet contains only a 32 bit #LSAs field */
452 while (lsa_counter < lsa_nr) {
453 offset = dissect_ospf_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
459 dissect_ospf_ls_ack(tvbuff_t *tvb, int offset, proto_tree *tree)
461 /* the body of a LS Ack packet simply contains zero or more LSA Headers */
462 while (tvb_reported_length_remaining(tvb, offset) != 0)
463 offset = dissect_ospf_lsa(tvb, offset, tree, FALSE);
467 * Returns if an LSA is opaque, i.e. requires special treatment
470 is_opaque(int lsa_type)
472 return (lsa_type >= OSPF_LSTYPE_OP_LINKLOCAL &&
473 lsa_type <= OSPF_LSTYPE_OP_ASWIDE);
476 /* MPLS/TE TLV types */
477 #define MPLS_TLV_ROUTER 1
478 #define MPLS_TLV_LINK 2
480 /* MPLS/TE Link STLV types */
488 MPLS_LINK_MAX_RES_BW,
493 static const value_string mpls_link_stlv_str[] = {
494 {MPLS_LINK_TYPE, "Link Type"},
495 {MPLS_LINK_ID, "Link ID"},
496 {MPLS_LINK_LOCAL_IF, "Local Interface IP Address"},
497 {MPLS_LINK_REMOTE_IF, "Remote Interface IP Address"},
498 {MPLS_LINK_TE_METRIC, "Traffic Engineering Metric"},
499 {MPLS_LINK_MAX_BW, "Maximum Bandwidth"},
500 {MPLS_LINK_MAX_RES_BW, "Maximum Reservable Bandwidth"},
501 {MPLS_LINK_UNRES_BW, "Unreserved Bandwidth"},
502 {MPLS_LINK_COLOR, "Resource Class/Color"},
507 * Dissect MPLS/TE opaque LSA
510 dissect_ospf_lsa_mpls(tvbuff_t *tvb, int offset, proto_tree *tree,
514 proto_tree *mpls_tree;
515 proto_tree *tlv_tree;
516 proto_tree *stlv_tree;
522 int stlv_type, stlv_len, stlv_offset;
526 ti = proto_tree_add_text(tree, tvb, offset, length,
527 "MPLS Traffic Engineering LSA");
528 mpls_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls);
530 while (length != 0) {
531 tlv_type = tvb_get_ntohs(tvb, offset);
532 tlv_length = tvb_get_ntohs(tvb, offset + 2);
533 tlv_end_offset = offset + tlv_length + 4;
537 case MPLS_TLV_ROUTER:
538 ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
539 "Router Address: %s",
540 ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
541 tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_router);
542 proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 1 - Router Address");
543 proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
545 proto_tree_add_text(tlv_tree, tvb, offset+4, 4, "Router Address: %s",
546 ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
550 ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
552 tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
553 proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 2 - Link Information");
554 proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
556 stlv_offset = offset + 4;
558 /* Walk down the sub-TLVs for link information */
559 while (stlv_offset < tlv_end_offset) {
560 stlv_type = tvb_get_ntohs(tvb, stlv_offset);
561 stlv_len = tvb_get_ntohs(tvb, stlv_offset + 2);
562 stlv_name = val_to_str(stlv_type, mpls_link_stlv_str, "Unknown sub-TLV");
566 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
568 tvb_get_guint8(tvb, stlv_offset + 4));
569 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
570 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
571 "TLV Type: %u: %s", stlv_type, stlv_name);
572 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
574 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "%s: %u", stlv_name,
575 tvb_get_guint8(tvb, stlv_offset + 4));
579 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
580 "%s: %s (%x)", stlv_name,
581 ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)),
582 tvb_get_ntohl(tvb, stlv_offset + 4));
583 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
584 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
585 "TLV Type: %u: %s", stlv_type, stlv_name);
586 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
588 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %s (%x)", stlv_name,
589 ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)),
590 tvb_get_ntohl(tvb, stlv_offset + 4));
593 case MPLS_LINK_LOCAL_IF:
594 case MPLS_LINK_REMOTE_IF:
595 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
597 ip_to_str(tvb_get_ptr(tvb, stlv_offset+4, 4)));
598 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
599 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
600 "TLV Type: %u: %s", stlv_type, stlv_name);
601 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
603 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %s", stlv_name,
604 ip_to_str(tvb_get_ptr(tvb, stlv_offset+4, 4)));
607 case MPLS_LINK_TE_METRIC:
608 case MPLS_LINK_COLOR:
609 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
611 tvb_get_ntohl(tvb, stlv_offset + 4));
612 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
613 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
614 "TLV Type: %u: %s", stlv_type, stlv_name);
615 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
617 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %u", stlv_name,
618 tvb_get_ntohl(tvb, stlv_offset + 4));
621 case MPLS_LINK_MAX_BW:
622 case MPLS_LINK_MAX_RES_BW:
623 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
624 "%s: %ld", stlv_name,
625 pieee_to_long(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
626 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
627 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
628 "TLV Type: %u: %s", stlv_type, stlv_name);
629 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
631 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %ld", stlv_name,
632 pieee_to_long(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
635 case MPLS_LINK_UNRES_BW:
636 ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
638 stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
639 proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
640 "TLV Type: %u: %s", stlv_type, stlv_name);
641 proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
643 for (i = 0; i < 8; i++) {
644 proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+(i*4), 4,
646 pieee_to_long(tvb_get_ptr(tvb, stlv_offset + 4 + i*4, 4)));
651 proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
652 "Unknown Link sub-TLV: %u", stlv_type);
655 stlv_offset += ((stlv_len+4+3)/4)*4;
660 ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
661 "Unknown LSA: %u", tlv_type);
662 tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
663 proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: %u - Unknown",
665 proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
667 proto_tree_add_text(tlv_tree, tvb, offset+4, tlv_length, "TLV Data");
671 offset += tlv_length + 4;
672 length -= tlv_length + 4;
677 * Dissect opaque LSAs
680 dissect_ospf_lsa_opaque(tvbuff_t *tvb, int offset, proto_tree *tree,
681 guint8 ls_id_type, guint32 length)
683 switch (ls_id_type) {
685 case OSPF_LSA_MPLS_TE:
686 dissect_ospf_lsa_mpls(tvb, offset, tree, length);
690 proto_tree_add_text(tree, tvb, offset, length,
691 "Unknown LSA Type %u", ls_id_type);
693 } /* switch on opaque LSA id */
697 dissect_ospf_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
698 gboolean disassemble_body)
700 proto_tree *ospf_lsa_tree;
712 guint16 link_counter;
717 /* AS-external LSA */
723 ls_type = tvb_get_guint8(tvb, offset + 3);
724 ls_length = tvb_get_ntohs(tvb, offset + 18);
725 end_offset = offset + ls_length;
728 case OSPF_LSTYPE_ROUTER:
729 lsa_type="Router LSA";
732 case OSPF_LSTYPE_NETWORK:
733 lsa_type="Network LSA";
736 case OSPF_LSTYPE_SUMMERY:
737 lsa_type="Summary LSA";
740 case OSPF_LSTYPE_ASBR:
744 case OSPF_LSTYPE_ASEXT:
745 lsa_type="AS-external-LSA";
748 case OSPF_LSTYPE_ASEXT7:
749 lsa_type="AS-external-LSA Type 7/NSSA";
752 case OSPF_LSTYPE_OP_LINKLOCAL:
753 lsa_type="Opaque LSA, Link-local scope";
756 case OSPF_LSTYPE_OP_AREALOCAL:
757 lsa_type="Opaque LSA, Area-local scope";
760 case OSPF_LSTYPE_OP_ASWIDE:
761 lsa_type="Opaque LSA, AS-wide scope";
769 if (disassemble_body) {
770 ti = proto_tree_add_text(tree, tvb, offset, ls_length,
771 "%s (Type: %u)", lsa_type, ls_type);
773 ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
776 ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
778 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
779 tvb_get_ntohs(tvb, offset));
780 dissect_ospf_options(tvb, offset + 2, ospf_lsa_tree);
781 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 3, 1, "LSA Type: %u (%s)",
784 if (is_opaque(ls_type)) {
785 ls_id_type = tvb_get_guint8(tvb, offset + 4);
786 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 1, "Link State ID Opaque Type: %u",
788 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3, "Link State ID Opaque ID: %u",
789 tvb_get_ntoh24(tvb, offset + 5));
792 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
793 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
796 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Advertising Router: %s",
797 ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
798 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%04x",
799 tvb_get_ntohl(tvb, offset + 12));
800 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
801 tvb_get_ntohs(tvb, offset + 16));
803 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
806 /* skip past the LSA header to the body */
807 offset += OSPF_LSA_HEADER_LENGTH;
808 ls_length -= OSPF_LSA_HEADER_LENGTH;
810 if (!disassemble_body)
815 case OSPF_LSTYPE_ROUTER:
816 /* again: flags should be secified in detail */
817 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x",
818 tvb_get_guint8(tvb, offset));
819 nr_links = tvb_get_ntohs(tvb, offset + 2);
820 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "Number of Links: %u",
823 /* nr_links links follow
824 * maybe we should put each of the links into its own subtree ???
826 for (link_counter = 1; link_counter <= nr_links; link_counter++) {
827 /* check the Link Type and ID */
828 link_type = tvb_get_guint8(tvb, offset + 8);
832 link_type_str="Point-to-point connection to another router";
833 link_id="Neighboring router's Router ID";
836 case OSPF_LINK_TRANSIT:
837 link_type_str="Connection to a transit network";
838 link_id="IP address of Designated Router";
842 link_type_str="Connection to a stub network";
843 link_id="IP network/subnet number";
846 case OSPF_LINK_VIRTUAL:
847 link_type_str="Virtual link";
848 link_id="Neighboring router's Router ID";
852 link_type_str="Unknown link type";
853 link_id="Unknown link ID";
857 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "%s: %s", link_id,
858 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
860 /* link_data should be specified in detail (e.g. network mask) (depends on link type)*/
861 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link Data: %s",
862 ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
864 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 1, "Link Type: %u - %s",
865 link_type, link_type_str);
866 nr_tos = tvb_get_guint8(tvb, offset + 9);
867 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 9, 1, "Number of TOS metrics: %u",
869 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 10, 2, "TOS 0 metric: %u",
870 tvb_get_ntohs(tvb, offset + 10));
874 /* nr_tos metrics may follow each link
875 * ATTENTION: TOS metrics are not tested (I don't have TOS
877 * please send me a mail if it is/isn't working
879 for (tos_counter = 1; tos_counter <= nr_tos; tos_counter++) {
880 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
881 tvb_get_guint8(tvb, offset),
882 tvb_get_ntohs(tvb, offset + 2));
888 case OSPF_LSTYPE_NETWORK:
889 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
890 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
893 while (offset < end_offset) {
894 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
895 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
900 case OSPF_LSTYPE_SUMMERY:
901 /* Type 3 and 4 LSAs have the same format */
902 case OSPF_LSTYPE_ASBR:
903 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
904 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
907 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Metric: %u",
908 tvb_get_ntoh24(tvb, offset + 1));
911 /* TOS-specific information, if any */
912 while (offset < end_offset) {
913 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
914 tvb_get_guint8(tvb, offset),
915 tvb_get_ntoh24(tvb, offset + 1));
920 case OSPF_LSTYPE_ASEXT:
921 case OSPF_LSTYPE_ASEXT7:
922 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
923 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
926 options = tvb_get_guint8(tvb, offset);
927 if (options & 0x80) { /* check wether or not E bit is set */
928 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
929 "External Type: Type 2 (metric is larger than any other link state path)");
931 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
932 "External Type: Type 1 (metric is specified in the same units as interface cost)");
934 /* the metric field of a AS-external LAS is specified in 3 bytes */
935 proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3, "Metric: %u",
936 tvb_get_ntoh24(tvb, offset + 1));
939 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
940 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
943 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
944 tvb_get_ntohl(tvb, offset));
947 /* TOS-specific information, if any */
948 while (offset < end_offset) {
949 options = tvb_get_guint8(tvb, offset);
950 if (options & 0x80) { /* check wether or not E bit is set */
951 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
952 "External Type: Type 2 (metric is larger than any other link state path)");
954 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
955 "External Type: Type 1 (metric is specified in the same units as interface cost)");
957 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
959 tvb_get_ntoh24(tvb, offset + 1));
962 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
963 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
966 proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
967 tvb_get_ntohl(tvb, offset));
972 case OSPF_LSTYPE_OP_LINKLOCAL:
973 case OSPF_LSTYPE_OP_AREALOCAL:
974 case OSPF_LSTYPE_OP_ASWIDE:
975 dissect_ospf_lsa_opaque(tvb, offset, ospf_lsa_tree, ls_id_type,
981 /* unknown LSA type */
982 proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
987 /* return the offset of the next LSA */
992 dissect_ospf_options(tvbuff_t *tvb, int offset, proto_tree *tree)
995 char options_string[20] = "";
997 /* ATTENTION !!! no check for length of options string */
998 options = tvb_get_guint8(tvb, offset);
999 if (options & OSPF_OPTIONS_E)
1000 strcat(options_string, "E");
1001 if (options & OSPF_OPTIONS_MC) {
1002 if (options_string[0] != '\0')
1003 strcat(options_string, "/");
1004 strcat(options_string, "MC");
1006 if (options & OSPF_OPTIONS_NP) {
1007 if (options_string[0] != '\0')
1008 strcat(options_string, "/");
1009 strcat(options_string, "NP");
1011 if (options & OSPF_OPTIONS_EA) {
1012 if (options_string[0] != '\0')
1013 strcat(options_string, "/");
1014 strcat(options_string, "EA");
1016 if (options & OSPF_OPTIONS_DC) {
1017 if (options_string[0] != '\0')
1018 strcat(options_string, "/");
1019 strcat(options_string, "DC");
1022 proto_tree_add_text(tree, tvb, offset, 1, "Options: 0x%x (%s)",
1023 options, options_string);
1027 proto_register_ospf(void)
1029 /* static hf_register_info hf[] = {
1031 { "Name", "ospf.abbreviation", TYPE, VALS_POINTER }},
1033 static gint *ett[] = {
1042 &ett_ospf_lsa_mpls_router,
1043 &ett_ospf_lsa_mpls_link,
1044 &ett_ospf_lsa_mpls_link_stlv
1047 proto_ospf = proto_register_protocol("Open Shortest Path First",
1049 /* proto_register_field_array(proto_ospf, hf, array_length(hf));*/
1050 proto_register_subtree_array(ett, array_length(ett));
1054 proto_reg_handoff_ospf(void)
1056 dissector_add("ip.proto", IP_PROTO_OSPF, dissect_ospf);